Initial commit of an esx/esxi driver for the lab plugin (thanks to kernelsmith). Also updated documentation in lib/lab/README.
git-svn-id: file:///home/svn/framework3/trunk@13151 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
7737cb22d9
commit
24d2b48f64
|
@ -1,61 +1,81 @@
|
|||
This folder contains the libraries necessary to run the lab plugin, and can also be used in a standalone way to automate virtual machines.
|
||||
|
||||
Currently you will need to have this code running on a linux box, and your VMHost will likely need to be linux as well. If you're interested in porting it to windows, please contact jcran@metasploit.com.
|
||||
|
||||
#########
|
||||
CONCEPTS:
|
||||
#########
|
||||
|
||||
The lab is designed to provided a clean interface to common vm functions such as start / stop / snapshot / revert and even running system commands. It's designed in an easily-extensible way, so that different VM technologies have the same interface, and you can ignore the specifics of the VM tech. The majority of the functionality is implemented in the form of drivers and controllers. Drivers implement the underlying command for each vm (such as start/stop/revert), whereas controllers implement the commands which apply to all vms (such as listing all running vms).
|
||||
|
||||
Drivers: Drivers implement the underlying command for each vm (such as start/stop/revert)
|
||||
If you're interested in porting a technology (see below), please take a look at the workstation_driver.rb and the workstation_controller.rb -- This is the most simple driver / controller in the lab, and you can simply copy / modify this to implement a new technology.
|
||||
|
||||
Controllers: Controllers implement the commands which apply to all vms (such as listing all running vms)
|
||||
##########################
|
||||
SUPPORTED VM TECHNOLOGIES:
|
||||
##########################
|
||||
|
||||
Currently Supported:
|
||||
workstation (wraps vmrun command)
|
||||
workstation_vixr (uses the vixr gem from rhythmx)
|
||||
remote_workstation (wraps vmrun command on a remote host)
|
||||
virtualbox
|
||||
dynagen (underlying vm for GNS3 - cisco hardware)
|
||||
Planned:
|
||||
qemu
|
||||
qemudo
|
||||
amazon
|
||||
others?
|
||||
Implemented:
|
||||
- workstation (Tested against 7.x)
|
||||
- remote_workstation (Tested against 7.x)
|
||||
- virtualbox (Tested against 4.x)
|
||||
|
||||
DEPENDENCIES:
|
||||
- whatever vm software is necessary for the driver you're using
|
||||
Partially Implemented:
|
||||
- remote_esxi (VMware ESX Host Agent 4.1.0 build-348481)
|
||||
- workstation_vixr (via the vixr gem)
|
||||
- dynagen
|
||||
|
||||
Need Implementation:
|
||||
- qemu
|
||||
- qemudo
|
||||
- amazon_ec2
|
||||
- others?
|
||||
|
||||
#################
|
||||
PLATFORM SUPPORT:
|
||||
#################
|
||||
|
||||
You will need to have this code running on a linux box, Currently this has only been run / tested on Ubuntu 9.04 -> 10.04, though it should run on any linux with an ssh client and the dependencies below. Remote VM Hosts will need to be linux as well, though other platforms may work (untested). If you're interested in porting it to windows, please contact me (jcran).
|
||||
|
||||
Platform Dependencies:
|
||||
- whatever vm software is necessary for the driver you're using (see SUPPORTED VM TECHNOLOGIES)
|
||||
- net/ssh - the gem (net-ssh), not the msf library. Required to perform ssh_exec in the case tools are not installed on the device. Not necessary if tools are installed.
|
||||
- net/scp - the gem (net-scp). Required to copy files to/from the devices in the case that tools are not installed. Not necessary if tools are installed.
|
||||
- vixr - required to use the workstation_vixr driver
|
||||
- fog - required to use the fog_amazon driver
|
||||
- vixr - required to use the workstation_vixr driver.
|
||||
|
||||
###########
|
||||
LAB PLUGIN:
|
||||
###########
|
||||
######################
|
||||
INTERFACE: LAB PLUGIN:
|
||||
######################
|
||||
|
||||
BACKGROUND:
|
||||
The lab plugin adds a number of commands which may be useful if you're interested in automating remote hosts with rc scripts. If you are testing an IPS / IDS, or determing if an exploit was successful, you'll need to have targets which can be easily started / reverted. The lab plugin provides those commands.
|
||||
|
||||
The lab plugin for msfconsole adds a number of commands which may be useful if you're interested in automating remote hosts with rc scripts, or if you need to control targets / support systems while utilizing the metasploit console. A potential use case is testing an IPS / IDS, and resetting the target after running each exploit.
|
||||
|
||||
USAGE:
|
||||
msf> load lab
|
||||
msf> lab_help
|
||||
msf> lab_load <path_to_lab_file> // see data/lab/test_targets.yml for an example
|
||||
msf> lab_start vm1
|
||||
msf> lab_snapshot vm1 emosheep
|
||||
// do some stuff
|
||||
msf> lab_revert vm1 emosheep
|
||||
msf> lab_stop vm1
|
||||
|
||||
###########
|
||||
STANDALONE:
|
||||
###########
|
||||
Here's some example usage for the lab plugin.
|
||||
|
||||
msf> load lab // Loads the lab plugin
|
||||
msf> lab_load <path_to_lab_file> // Loads from a lab configuration file. See data/lab/test_targets.yml for an example
|
||||
msf> lab_load_dir workstation /path/to/vmx/files // Loads from a local directory.
|
||||
msf> lab_load_running remote_esx root esx_server // Loads all running vms.
|
||||
msf> lab_start vm1 // Start a vm which was loaded above
|
||||
msf> lab_snapshot vm1 snapshot_1 // Snapshot a vm as 'snapshot_1'
|
||||
msf> lab_run_command ("rm -rf /") // oops!
|
||||
msf> lab_show // Show all vms that we're aware of
|
||||
msf> lab_show_running // Show only running vms
|
||||
msf> lab_start vm2 // Start another vm
|
||||
msf> lab_suspend vm1 // Suspend a vm
|
||||
msf> lab_revert all snapshot_1 // Revert all vms back to 'snapshot_1'
|
||||
|
||||
###############
|
||||
STANDALONE API:
|
||||
###############
|
||||
|
||||
BACKGROUND:
|
||||
The lab libraries add tons of useful functionality that isn't exposed through the lab plugin, such as the ability to run commands on hosts. This library can serve as an excellent base for more complex operations on a remote host as well.
|
||||
|
||||
The lab libraries add tons of useful functionality that isn't exposed through the lab plugin, such as the ability to run commands on hosts. This library can serve as an excellent base for more complex operations on a remote host as well.
|
||||
|
||||
USAGE:
|
||||
You must first create a yaml file which describes your vm. See data/lab/test_targets.yml for an example.
|
||||
|
||||
You must first create a yaml file which describes your vm. See data/lab/test_targets.yml for an example.
|
||||
|
||||
require 'vm_controller'
|
||||
vm_controller = ::Lab::Controllers::VmController.new(YAML.load_file(lab_def))
|
||||
|
@ -64,3 +84,5 @@ USAGE:
|
|||
vm_controller['vm1'].run_command("rm /etc/resolv.conf")
|
||||
vm_controller['vm1'].open_uri("http://autopwn:8080")
|
||||
vm_controller['vm1'].revert("clean")
|
||||
vm_controller['vm1'].revert("clean")
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# This controller was built against:
|
||||
# VMware ESX Host Agent 4.1.0 build-348481
|
||||
|
||||
module Lab
|
||||
module Controllers
|
||||
module RemoteEsxController
|
||||
|
||||
# Note that 3.5 was different (vmware-vim-cmd)
|
||||
VIM_CMD = 'vim-cmd'.freeze
|
||||
|
||||
def self.dir_list(basepath=nil)
|
||||
# Does this method really even make sense for esx?
|
||||
return "Unsupported :("
|
||||
end
|
||||
|
||||
def self.running_list(user, host)
|
||||
user.gsub!(/(\W)*/, '')
|
||||
host.gsub!(/(\W)*/, '')
|
||||
|
||||
# first get all registered vms
|
||||
registered_vms = self.get_vms(user, host) || []
|
||||
running_vms = []
|
||||
|
||||
# now let's see which ones are running
|
||||
# TODO: this is ghetto, would be better not to connect repeatedly
|
||||
registered_vms.each do |vm|
|
||||
remote_cmd = "ssh #{user}@#{host} \"#{VIM_CMD} vmsvc/power.getstate #{vm[:id]}\""
|
||||
raw = `#{remote_cmd}`
|
||||
running_vms << vm if raw =~ /Powered on/
|
||||
end
|
||||
|
||||
return running_vms
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.get_vms(user, host)
|
||||
user.gsub!(/(\W)*/, '')
|
||||
host.gsub!(/(\W)*/, '')
|
||||
|
||||
vms = [] # array of VM hashes
|
||||
remote_cmd = "ssh #{user}@#{host} \"#{VIM_CMD} vmsvc/getallvms | grep ^[0-9] | sed 's/[[:blank:]]\\{3,\\}/ /g'\""
|
||||
raw = `#{remote_cmd}`.split("\n")
|
||||
|
||||
raw.each do |line|
|
||||
# So effing ghetto
|
||||
id_and_name = line.split('[datastore').first
|
||||
id = id_and_name.split(' ').first
|
||||
|
||||
## TODO - there's surely a better way to do this.
|
||||
name_array = id_and_name.split(' ')
|
||||
name_array.shift
|
||||
name = name_array.join(' ')
|
||||
vms << {:id => id, :name => name}
|
||||
end
|
||||
|
||||
return vms
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,122 @@
|
|||
require 'vm_driver'
|
||||
|
||||
##
|
||||
## $Id: remote_esx_driver.rb 12713 2011-05-25 07:30:22Z jcran $
|
||||
##
|
||||
|
||||
# This driver was built against:
|
||||
# VMware ESX Host Agent 4.1.0 build-348481
|
||||
|
||||
|
||||
module Lab
|
||||
module Drivers
|
||||
|
||||
class RemoteEsxDriver < VmDriver
|
||||
|
||||
attr_accessor :location # among other things
|
||||
|
||||
def initialize(vmid, location, os=nil, tools=false, user=nil, host=nil, credentials=nil)
|
||||
|
||||
unless user then raise ArgumentError, "Must provide a username" end
|
||||
unless host then raise ArgumentError, "Must provide a hostname" end
|
||||
|
||||
@vmid = filter_input(vmid)
|
||||
@location = filter_input(location)
|
||||
@user = filter_input(user)
|
||||
@host = filter_input(host)
|
||||
@credentials = credentials # individually filtered
|
||||
@tools = tools # not used in command lines, no filter
|
||||
@os = os # not used in command lines, no filter
|
||||
|
||||
# TODO - Currently only implemented for the first set
|
||||
if @credentials.count > 0
|
||||
@vm_user = filter_input(@credentials[0]['user'])
|
||||
@vm_pass = filter_input(@credentials[0]['pass'])
|
||||
@vm_keyfile = filter_input(@credentials[0]['keyfile'])
|
||||
end
|
||||
end
|
||||
|
||||
def start
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.on #{@vmid}\"")
|
||||
end
|
||||
|
||||
def stop
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.off #{@vmid}\"")
|
||||
end
|
||||
|
||||
def suspend
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.suspend #{@vmid}\"")
|
||||
end
|
||||
|
||||
def pause # no concept of pause?
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.suspend #{@vmid}\"")
|
||||
end
|
||||
|
||||
def resume
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.suspendResume #{@vmid}\"")
|
||||
end
|
||||
|
||||
def reset
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.reset #{@vmid}\"")
|
||||
end
|
||||
|
||||
def create_snapshot(snapshot)
|
||||
snapshot = filter_input(snapshot)
|
||||
|
||||
#vmware-vim-cmd vmsvc/snapshot.create [vmid: int] [snapshotName: string]
|
||||
# [snapshotDescription: string] [includeMemory:bool]
|
||||
|
||||
system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.create #{@vmid} #{snapshot} \'lab created snapshot\' 1 true\"")
|
||||
end
|
||||
|
||||
def revert_snapshot(snapshot)
|
||||
raise "Not Implemented"
|
||||
|
||||
#vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int]
|
||||
# not sure how we can do this, would have to list snapshots and map name to level & index
|
||||
|
||||
#snapshot = filter_input(snapshot)
|
||||
#system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.revert #{@vmid} 0 0\"")
|
||||
end
|
||||
|
||||
def delete_snapshot(snapshot)
|
||||
raise "Not Implemented"
|
||||
|
||||
#snapshot = filter_input(snapshot)
|
||||
#system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.remove #{@vmid} true 0 0\"")
|
||||
end
|
||||
|
||||
def run_command(command)
|
||||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def check_file_exists(file)
|
||||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def create_directory(directory)
|
||||
raise "Not Implemented"
|
||||
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/
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -7,7 +7,6 @@ module RemoteWorkstationController
|
|||
host.gsub!(/(\W)*/, '')
|
||||
|
||||
remote_cmd = "ssh #{user}@#{host} \"vmrun list nogui\""
|
||||
puts "running #{remote_cmd}"
|
||||
vm_list = `#{remote_cmd}`.split("\n")
|
||||
vm_list.shift
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ module Drivers
|
|||
raise ArgumentError,"Error, no vm at: #{@location}"
|
||||
end
|
||||
|
||||
puts "Registering #{@location}"
|
||||
# Registering @location
|
||||
@vmid = register_and_return_vmid
|
||||
end
|
||||
|
||||
|
|
|
@ -7,16 +7,17 @@ require 'workstation_vixr_driver'
|
|||
require 'remote_workstation_driver'
|
||||
require 'virtualbox_driver'
|
||||
require 'dynagen_driver'
|
||||
#require 'fog_amazon_driver'
|
||||
#require 'amazon_driver'
|
||||
require 'remote_esx_driver'
|
||||
#require 'qemu_driver'
|
||||
#require 'qemudo_driver'
|
||||
|
||||
#require 'amazon_driver'
|
||||
|
||||
module Lab
|
||||
class Vm
|
||||
|
||||
attr_accessor :vmid
|
||||
attr_accessor :name
|
||||
attr_accessor :descripition
|
||||
attr_accessor :location
|
||||
attr_accessor :driver
|
||||
attr_accessor :credentials
|
||||
|
@ -32,6 +33,7 @@ class Vm
|
|||
## driver (vm technology)
|
||||
## user (if applicable - remote system)
|
||||
## host (if applicable - remote system)
|
||||
## pass (if applicable - remote system)
|
||||
## location (file / uri)
|
||||
## credentials (of the form [ {'user'=>"user",'pass'=>"pass", 'admin' => false}, ... ])
|
||||
## os (currently only linux / windows)
|
||||
|
@ -45,13 +47,16 @@ class Vm
|
|||
@driver = nil
|
||||
@driver_type = filter_input(config['driver'])
|
||||
@driver_type.downcase!
|
||||
|
||||
@type = filter_input(config['type']) || "unspecified"
|
||||
|
||||
@name = config['name'] || "" # not used in command lines
|
||||
@description = config['description'] || "" # not used in command lines
|
||||
@tools = config['tools'] || false # don't filter this, not used in cmdlines
|
||||
@os = config['os'] || nil
|
||||
@arch = config['arch'] || nil
|
||||
|
||||
@type = filter_input(config['type']) || "unspecified"
|
||||
@credentials = config['credentials'] || []
|
||||
|
||||
|
||||
# Optional for virtualbox
|
||||
@location = filter_input(config['location'])
|
||||
|
||||
|
@ -59,11 +64,12 @@ class Vm
|
|||
@user = filter_input(config['user']) || nil
|
||||
@host = filter_input(config['host']) || nil
|
||||
|
||||
# pass might need to be unfiltered, or filtered less
|
||||
@pass = filter_input(config['pass']) || nil
|
||||
|
||||
#Only dynagen
|
||||
@platform = config['platform']
|
||||
|
||||
#puts "DEBUG: " + driver_type + " driver requested."
|
||||
|
||||
if @driver_type == "workstation"
|
||||
@driver = Lab::Drivers::WorkstationDriver.new(@vmid, @location, @os, @tools, @credentials)
|
||||
elsif @driver_type == "workstation_vixr"
|
||||
|
@ -74,8 +80,8 @@ class Vm
|
|||
@driver = Lab::Drivers::VirtualBoxDriver.new(@vmid, @location, @credentials)
|
||||
elsif @driver_type == "dynagen"
|
||||
@driver = Lab::Drivers::DynagenDriver.new(@vmid, @location,@platform)
|
||||
#elsif @driver_type == "fog_amazon"
|
||||
# @driver = Lab::Drivers::FogAmazonDriver.new
|
||||
elsif @driver_type == "remote_esx"
|
||||
@driver = Lab::Drivers::RemoteEsxDriver.new(@vmid, @location, @os, @tools, @user, @host, @credentials)
|
||||
#elsif @driver_type == "qemu"
|
||||
# @driver = Lab::Drivers::QemuDriver.new
|
||||
#elsif @driver_type == "qemudo"
|
||||
|
@ -198,7 +204,7 @@ private
|
|||
def filter_input(string)
|
||||
return unless string
|
||||
|
||||
if !(string =~ /^[\d*\w*\s*\[\]\{\}\/\\\.\-\"\(\)]*$/)
|
||||
if !(string =~ /^[(!)\d*\w*\s*\[\]\{\}\/\\\.\-\"\(\)]*$/)
|
||||
raise "WARNING! Invalid character in: #{string}"
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
##
|
||||
##
|
||||
|
||||
$:.unshift(File.expand_path(File.dirname(__FILE__))) ## Msf Test libraries
|
||||
$:.unshift(File.expand_path(File.dirname(__FILE__)))
|
||||
|
||||
require 'find'
|
||||
require 'enumerator'
|
||||
|
@ -16,8 +16,7 @@ require 'workstation_vixr_controller'
|
|||
require 'remote_workstation_controller'
|
||||
require 'virtualbox_controller'
|
||||
require 'dynagen_controller'
|
||||
|
||||
#require 'fog_amazon_controller'
|
||||
require 'remote_esx_controller'
|
||||
#require 'qemu_controller'
|
||||
#require 'qemudo_controller'
|
||||
#require 'amazon_controller'
|
||||
|
@ -32,7 +31,7 @@ module Controllers
|
|||
include Lab::Controllers::RemoteWorkstationController
|
||||
include Lab::Controllers::VirtualBoxController
|
||||
include Lab::Controllers::DynagenController
|
||||
#include Lab::Controllers::FogAmazonController
|
||||
include Lab::Controllers::RemoteEsxController
|
||||
#include Lab::Controllers::QemuController
|
||||
#include Lab::Controllers::QemudoController
|
||||
#include Lab::Controllers::AmazonController
|
||||
|
@ -89,6 +88,7 @@ module Controllers
|
|||
vm = Vm.new(item)
|
||||
@vms << vm unless includes_vmid? vm.vmid
|
||||
rescue Exception => e
|
||||
# TODO - this needs to go into a logfile and be raised up to an interface.
|
||||
puts "Invalid VM definition"
|
||||
puts "Exception: #{e.to_s}"
|
||||
end
|
||||
|
@ -128,6 +128,10 @@ module Controllers
|
|||
vm_list = ::Lab::Controllers::RemoteWorkstationController::dir_list(dir)
|
||||
elsif driver_type.downcase == "virtualbox"
|
||||
vm_list = ::Lab::Controllers::VirtualBoxController::dir_list(dir)
|
||||
elsif driver_type.downcase == "remote_esx"
|
||||
vm_list =::Lab::Controllers::RemoteEsxController::dir_list(dir)
|
||||
#elsif driver_type.downcase == "esxi_vixr"
|
||||
# vm_list =::Lab::Controllers::EsxiVixrController::dir_list(dir)
|
||||
#elsif driver_type.downcase == "fog_amazon"
|
||||
# vm_list = ::Lab::Controllers::FogAmazonController::dir_list(dir)
|
||||
else
|
||||
|
@ -135,7 +139,6 @@ module Controllers
|
|||
end
|
||||
|
||||
vm_list.each_index do |index|
|
||||
puts "Creating VM object for: " + vm_list[index]
|
||||
@vms << Vm.new( {'vmid' => "vm_#{index}", 'driver' => driver_type, 'location' => vm_list[index]} )
|
||||
end
|
||||
end
|
||||
|
@ -182,11 +185,24 @@ module Controllers
|
|||
when :virtualbox
|
||||
vm_list = ::Lab::Controllers::VirtualBoxController::running_list
|
||||
|
||||
# TODO - why are user and host specified here?
|
||||
|
||||
vm_list.each do |item|
|
||||
## Add it to the vm list
|
||||
@vms << Vm.new( { 'vmid' => "#{item}",
|
||||
'driver' => driver_type,
|
||||
'location' => nil, # this will be filled in by the driver
|
||||
'user' => user,
|
||||
'host' => host } )
|
||||
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]}",
|
||||
'driver' => driver_type,
|
||||
'location' => nil,
|
||||
'user' => user,
|
||||
'host' => host } )
|
||||
end
|
||||
|
|
|
@ -15,70 +15,79 @@ module Drivers
|
|||
class VmDriver
|
||||
|
||||
def register # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def unregister # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def start # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def stop # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def suspend # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def pause # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def resume # Must be implemented in a child *_driver class
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def reset # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def create_snapshot(snapshot) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def revert_snapshot(snapshot) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def delete_snapshot(snapshot) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def run_command(command) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def copy_from(from, to) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def copy_to(from, to) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def check_file_exists(file) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def create_directory(directory) # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def cleanup # Must be implemented in a child *_driver class
|
||||
raise Exception, "Command Not Implemented"
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Currently this requires the net-ssh and net-scp gems. Ran into problems doing
|
||||
# it with within metasploit (even though net-ssh is available). TODO - do something
|
||||
# about this...
|
||||
|
||||
def scp_to(from,to)
|
||||
gem 'net-ssh'
|
||||
require 'net/ssh'
|
||||
|
@ -129,7 +138,7 @@ private
|
|||
end
|
||||
|
||||
def filter_input(string)
|
||||
return unless string
|
||||
return "" unless string
|
||||
|
||||
if !(string =~ /^[\w\s\[\]\{\}\/\\\.\-\"\(\):]*$/)
|
||||
raise "WARNING! Invalid character in: #{string}"
|
||||
|
@ -140,7 +149,6 @@ private
|
|||
|
||||
def system_command(command)
|
||||
begin
|
||||
#puts "DEBUG: running command #{command}"
|
||||
system(command)
|
||||
rescue Exception => e
|
||||
return false
|
||||
|
|
108
plugins/lab.rb
108
plugins/lab.rb
|
@ -48,55 +48,7 @@ class Plugin::Lab < Msf::Plugin
|
|||
def name
|
||||
"Lab"
|
||||
end
|
||||
|
||||
##
|
||||
## Commands for help
|
||||
##
|
||||
|
||||
def longest_cmd_size
|
||||
commands.keys.map {|x| x.size}.sort.last
|
||||
end
|
||||
|
||||
# No extended help yet, but this is where more detailed documentation
|
||||
# on particular commands would live. Key is command, (not cmd_command),
|
||||
# value is the documentation.
|
||||
def extended_help
|
||||
{
|
||||
"lab_fake_cmd" => "This is a fake command. It's got its own special docs." +
|
||||
(" " * longest_cmd_size) + "It might be long so so deal with formatting somehow."
|
||||
}
|
||||
end
|
||||
|
||||
# Map for usages
|
||||
def lab_usage
|
||||
caller[0][/`cmd_(.*)'/]
|
||||
cmd = $1
|
||||
if extended_help[cmd] || commands[cmd]
|
||||
cmd_lab_help cmd
|
||||
else # Should never really get here...
|
||||
print_error "Unknown command. Try 'help'"
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_lab_help(*args)
|
||||
if args.empty?
|
||||
commands.each_pair {|k,v| print_line "%-#{longest_cmd_size}s - %s" % [k,v] }
|
||||
else
|
||||
args.each do |c|
|
||||
if extended_help[c] || commands[c]
|
||||
print_line "%-#{longest_cmd_size}s - %s" % [c,extended_help[c] || commands[c]]
|
||||
else
|
||||
print_error "Unknown command '#{c}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print_line
|
||||
print_line "In order to use this plugin, you'll want to configure a .yml lab file"
|
||||
print_line "You can find an example in data/lab/test_targets.yml"
|
||||
print_line
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
## Regular Lab Commands
|
||||
##
|
||||
|
@ -337,6 +289,56 @@ class Plugin::Lab < Msf::Plugin
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
## Commands for help
|
||||
##
|
||||
|
||||
def longest_cmd_size
|
||||
commands.keys.map {|x| x.size}.sort.last
|
||||
end
|
||||
|
||||
# No extended help yet, but this is where more detailed documentation
|
||||
# on particular commands would live. Key is command, (not cmd_command),
|
||||
# value is the documentation.
|
||||
def extended_help
|
||||
{
|
||||
"lab_fake_cmd" => "This is a fake command. It's got its own special docs." +
|
||||
(" " * longest_cmd_size) + "It might be long so so deal with formatting somehow."
|
||||
}
|
||||
end
|
||||
|
||||
# Map for usages
|
||||
def lab_usage
|
||||
caller[0][/`cmd_(.*)'/]
|
||||
cmd = $1
|
||||
if extended_help[cmd] || commands[cmd]
|
||||
cmd_lab_help cmd
|
||||
else # Should never really get here...
|
||||
print_error "Unknown command. Try 'help'"
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_lab_help(*args)
|
||||
if args.empty?
|
||||
commands.each_pair {|k,v| print_line "%-#{longest_cmd_size}s - %s" % [k,v] }
|
||||
else
|
||||
args.each do |c|
|
||||
if extended_help[c] || commands[c]
|
||||
print_line "%-#{longest_cmd_size}s - %s" % [c,extended_help[c] || commands[c]]
|
||||
else
|
||||
print_error "Unknown command '#{c}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print_line
|
||||
print_line "In order to use this plugin, you'll want to configure a .yml lab file"
|
||||
print_line "You can find an example in data/lab/test_targets.yml"
|
||||
print_line
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def hlp_print_lab
|
||||
indent = ' '
|
||||
|
@ -344,11 +346,12 @@ class Plugin::Lab < Msf::Plugin
|
|||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'Available Lab VMs',
|
||||
'Indent' => indent.length,
|
||||
'Columns' => [ 'Vmid', 'Location', "Powered On" ]
|
||||
'Columns' => [ 'Vmid', 'Name', 'Location', "Power?" ]
|
||||
)
|
||||
|
||||
@controller.each do |vm|
|
||||
tbl << [ vm.vmid,
|
||||
tbl << [ vm.vmid,
|
||||
vm.name,
|
||||
vm.location,
|
||||
vm.running?]
|
||||
end
|
||||
|
@ -362,12 +365,13 @@ class Plugin::Lab < Msf::Plugin
|
|||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'Running Lab VMs',
|
||||
'Indent' => indent.length,
|
||||
'Columns' => [ 'Vmid', 'Location', 'Powered On' ]
|
||||
'Columns' => [ 'Vmid', 'Name', 'Location', 'Power?' ]
|
||||
)
|
||||
|
||||
@controller.each do |vm|
|
||||
if vm.running?
|
||||
tbl << [ vm.vmid,
|
||||
vm.name,
|
||||
vm.location,
|
||||
vm.running?]
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue