updated to add improved esxi support

git-svn-id: file:///home/svn/framework3/trunk@13744 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Jonathan Cran 2011-09-17 03:00:57 +00:00
parent c0ddf56ec0
commit 3c40aba395
7 changed files with 81 additions and 42 deletions

View File

@ -13,8 +13,6 @@ class FogDriver < VmDriver
super(config) super(config)
@fog_config = fog_config @fog_config = fog_config
puts "Fog Config: #{fog_config}"
# Soft dependency # Soft dependency
begin begin
require 'fog' require 'fog'

View File

@ -13,12 +13,11 @@ module Drivers
class RemoteEsxDriver < VmDriver class RemoteEsxDriver < VmDriver
def initialize(config) def initialize(config)
unless config['user'] then raise ArgumentError, "Must provide a username" end unless config['user'] then raise ArgumentError, "Must provide a username" end
unless config['host'] then raise ArgumentError, "Must provide a hostname" end unless config['host'] then raise ArgumentError, "Must provide a hostname" end
super(config) super(config)
@user = filter_command(config['user']) @user = filter_command(config['user'])
@host = filter_command(config['host']) @host = filter_command(config['host'])
end end
@ -57,16 +56,22 @@ class RemoteEsxDriver < VmDriver
end end
def revert_snapshot(snapshot) def revert_snapshot(snapshot)
raise "Not Implemented"
snapshots = get_snapshots
#vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int] # Look through our snapshot list, choose the right one based on display_name
# not sure how we can do this, would have to list snapshots and map name to level & index snapshots.each do |snapshot_obj|
if snapshot_obj[:display_name].downcase == snapshot.downcase
#snapshot = filter_input(snapshot) snapshot_number = snapshot_obj[:name].join(" ")
#system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.revert #{@vmid} 0 0\"") system_command("ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.revert #{@vmid} #{snapshot_number}\"")
return true
end
end
# If we got here, the snapshot didn't exist
raise "Invalid Snapshot Name"
end end
def delete_snapshot(snapshot) def delete_snapshot(snapshot)
raise "Not Implemented" raise "Not Implemented"
@ -113,6 +118,43 @@ class RemoteEsxDriver < VmDriver
false false
end end
private
def get_snapshots
# Command take the format:
# vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int]
output = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.get #{@vmid}\"`
# this keeps track of the snapshots, takes the form:
#[ {:name => [0,0], :display_name => "String containing the snapshotname},
# {:name => [0,1], :display_name => "String containing the snapshotname}, ]
# ...
snapshots = []
# Use these to keep track of the parsing...
current_tree = -1
current_num = 0
count = 0
# Do the parsing & stick the snapshots in the snapshots array
output_lines = output.split("\n")
output_lines.each do |line|
if line.include?("|") # this is a new snapshot
if line.include?("ROOT") # it's a root
current_tree = current_tree + 1 # new tree
snapshots << { :name => [current_tree,current_num], :display_name => output_lines[count+1].split(":").last.strip }
current_num = 0
else
current_num = current_num + 1 # new snapshot in current tree
snapshots << { :name => [current_tree,current_num], :display_name => output_lines[count+1].split(":").last.strip }
end
end
count = count+1
end
snapshots
end
end end
end end

View File

@ -18,12 +18,13 @@ class VmDriver
attr_accessor :tools attr_accessor :tools
attr_accessor :credentials attr_accessor :credentials
def initialize(basic_driver_config) def initialize(config)
@vmid = filter_command(basic_driver_config["vmid"])
@location = filter_command(basic_driver_config["location"]) @vmid = filter_command(config["vmid"].to_s)
@credentials = basic_driver_config["credentials"] || [] @location = filter_command(config["location"])
@tools = filter_input(basic_driver_config["tools"]) @credentials = config["credentials"] || []
@os = filter_input(basic_driver_config["os"]) @tools = filter_input(config["tools"])
@os = filter_input(config["os"])
# Currently only implemented for the first set # Currently only implemented for the first set
if @credentials.count > 0 if @credentials.count > 0
@ -106,7 +107,7 @@ private
def scp_to(from,to) def scp_to(from,to)
require 'net/scp' require 'net/scp'
Net::SCP.start(@vmid, @vm_user, :password => @vm_pass) do |scp| Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
scp.upload!(from,to) scp.upload!(from,to)
end end
end end
@ -115,13 +116,13 @@ private
require 'net/scp' require 'net/scp'
# download a file from a remote server # download a file from a remote server
Net::SCP.start(@vmid, @vm_user, :password => @vm_pass) do |scp| Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
scp.download!(from,to) scp.download!(from,to)
end end
end end
def ssh_exec(command) def ssh_exec(command)
Net::SSH.start(@vmid, @vm_user, :password => @vm_pass) do |ssh| Net::SSH.start(@hostname, @vm_user, :password => @vm_pass) do |ssh|
result = ssh.exec!(command) result = ssh.exec!(command)
end end
end end
@ -130,7 +131,7 @@ private
return "" unless string # nil becomes empty string return "" unless string # nil becomes empty string
return unless string.class == String # Allow other types unmodified return unless string.class == String # Allow other types unmodified
if !(string =~ /^[0-9\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/) unless /^[\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
raise "WARNING! Invalid character in: #{string}" raise "WARNING! Invalid character in: #{string}"
end end
@ -141,7 +142,7 @@ private
return "" unless string # nil becomes empty string return "" unless string # nil becomes empty string
return unless string.class == String # Allow other types unmodified return unless string.class == String # Allow other types unmodified
if !(string =~ /^[0-9\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/) unless /^[\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
raise "WARNING! Invalid character in: #{string}" raise "WARNING! Invalid character in: #{string}"
end end

View File

@ -10,7 +10,7 @@ end
# This allows us to override the default way of running commands # This allows us to override the default way of running commands
# Currently useful for the esx controller # Currently useful for the esx controller
module Lab module Lab
class Vm class Vm
@ -20,7 +20,6 @@ class Vm
attr_accessor :session_input attr_accessor :session_input
attr_accessor :session_output attr_accessor :session_output
def create_framework def create_framework
return if @framework return if @framework
@framework = Msf::Simple::Framework.create @framework = Msf::Simple::Framework.create
@ -42,7 +41,7 @@ class Vm
if @os == "windows" if @os == "windows"
exploit_name = 'windows/smb/psexec' exploit_name = 'windows/smb/psexec'
payload_name = 'windows/meterpreter/bind_tcp' payload_name = 'windows/meterpreter/bind_tcp'
options = { "RHOST" => @vmid, options = { "RHOST" => @hostname,
"SMBUser" => @vm_user, "SMBUser" => @vm_user,
"SMBPass" => @vm_pass} "SMBPass" => @vm_pass}
@ -64,7 +63,7 @@ class Vm
else else
module_name = 'scanner/ssh/ssh_login' module_name = 'scanner/ssh/ssh_login'
payload_name = 'linux/x86/meterpreter/bind_tcp' payload_name = 'linux/x86/meterpreter/bind_tcp'
options = { "RHOSTS" => @vmid, options = { "RHOSTS" => @hostname,
"USERNAME" => @vm_user, "USERNAME" => @vm_user,
"PASSWORD" => @vm_pass, "PASSWORD" => @vm_pass,
"BLANK_PASSWORDS" => false, "BLANK_PASSWORDS" => false,

View File

@ -4,14 +4,6 @@
module Lab module Lab
module Modifier module Modifier
module Test module Test
def dhclient
run_command("sudo dhclient")
end
def route
run_command("route -n")
end
def install_nmap def install_nmap
run_command("sudo apt-get install nmap") run_command("sudo apt-get install nmap")
end end

View File

@ -1,3 +1,4 @@
require 'modifier/test_modifier' require 'modifier/test_modifier'
require 'modifier/backtrack5_modifier' require 'modifier/backtrack5_modifier'
require 'modifier/linux_modifier'
require 'modifier/meterpreter_modifier' require 'modifier/meterpreter_modifier'

View File

@ -31,11 +31,18 @@ class Vm
def initialize(config = {}) def initialize(config = {})
# TODO - This is such a mess. clean up, and pass stuff down to drivers # TODO - This is a mess. clean up, and pass stuff down to drivers
# and then rework the code that uses this api. # and then rework the code that uses this api.
@vmid = config['vmid'] @vmid = config['vmid'].to_s
raise "Invalid VMID" unless @vmid raise "Invalid VMID" unless @vmid
# Grab the hostname if specified, otherwise use the vmid
# VMID will be different in the case of ESX
@hostname = config['hostname']
if !@hostname
@hostname = @vmid
end
@driver_type = filter_input(config['driver']) @driver_type = filter_input(config['driver'])
@driver_type.downcase! @driver_type.downcase!
@ -86,8 +93,7 @@ class Vm
else else
raise "Unknown Driver Type" raise "Unknown Driver Type"
end end
# Load in a list of modifiers. These provide additional methods # Load in a list of modifiers. These provide additional methods
# Currently it is up to the user to verify that # Currently it is up to the user to verify that
# modifiers are properly used with the correct VM image. # modifiers are properly used with the correct VM image.
@ -145,8 +151,8 @@ class Vm
end end
def revert_and_start(snapshot) def revert_and_start(snapshot)
self.revert_snapshot(snapshot) @driver.revert_snapshot(snapshot)
self.start @driver.start
end end
def copy_to(from,to) def copy_to(from,to)
@ -225,7 +231,7 @@ private
return "" unless string # nil becomes empty string return "" unless string # nil becomes empty string
return unless string.class == String # Allow other types return unless string.class == String # Allow other types
if !(string =~ /^[(!)\d*\w*\s*\[\]\{\}\/\\\.\-\"\(\)]*$/) unless /^[(!)\d*\w*\s*\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
raise "WARNING! Invalid character in: #{string}" raise "WARNING! Invalid character in: #{string}"
end end