lab 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/lab.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
29
29
  s.add_runtime_dependency "net-ssh"
30
30
  s.add_runtime_dependency "net-scp"
31
31
 
32
- # Vmware ESX driver
32
+ # Vmware vsphere driver
33
33
  s.add_runtime_dependency "rbvmomi"
34
34
 
35
35
  end
@@ -9,7 +9,7 @@ module RemoteEsxiController
9
9
  VIM_CMD = 'vim-cmd'.freeze
10
10
 
11
11
  def self.dir_list(basepath=nil)
12
- # Does this method really even make sense for esx?
12
+ # Does this method really even make sense for esxi?
13
13
  return "Unsupported :("
14
14
  end
15
15
 
@@ -9,7 +9,7 @@ module RemoteEsxiController
9
9
  VIM_CMD = 'vim-cmd'.freeze
10
10
 
11
11
  def self.dir_list(basepath=nil)
12
- # Does this method really even make sense for esx?
12
+ # Does this method really even make sense for esxi?
13
13
  return "Unsupported :("
14
14
  end
15
15
 
@@ -47,7 +47,7 @@ private
47
47
  id_and_name = line.split('[datastore').first
48
48
  id = id_and_name.split(' ').first
49
49
 
50
- ## TODO - there's surely a better way to do this.
50
+ # TODO - there's surely a better way to do this.
51
51
  name_array = id_and_name.split(' ')
52
52
  name_array.shift
53
53
  name = name_array.join(' ')
@@ -4,5 +4,6 @@ require 'controller/fog_controller'
4
4
  require 'controller/dynagen_controller'
5
5
  require 'controller/remote_workstation_controller'
6
6
  require 'controller/remote_esxi_controller'
7
+ require 'controller/vsphere_controller'
7
8
  #require 'controller/qemu_controller'
8
9
  #require 'controller/qemudo_controller'
@@ -17,7 +17,7 @@ class FogDriver < VmDriver
17
17
  begin
18
18
  require 'fog'
19
19
  rescue LoadError
20
- raise "WARNING: Library fog not found. Could Not Create Driver"
20
+ raise "WARNING: Library fog not found. Could not create driver"
21
21
  end
22
22
 
23
23
  if @fog_config['fog_type'] == "ec2"
@@ -44,18 +44,17 @@ class FogDriver < VmDriver
44
44
  :aws_access_key_id => @aws_access_key_file,
45
45
  :aws_secret_access_key => @aws_secret_access_key_file )
46
46
  else
47
- raise "Unsupported Fog Type"
47
+ raise "Unsupported fog type"
48
48
  end
49
49
  end
50
50
 
51
51
  def start
52
52
  ec2_settings = {
53
- :image_id => @ec2_base_ami,
53
+ :image_id => @ec2_base_ami,
54
54
  :flavor_id => @ec2_flavor,
55
55
  :public_key_path => @ec2_instance_public_key_file,
56
56
  :private_key_path => @ec2_instance_private_key_file,
57
57
  :username => @ec2_user}
58
-
59
58
  begin
60
59
  @fog_server = @compute.servers.bootstrap(ec2_settings)
61
60
  rescue Fog::Compute::AWS::Error => e
@@ -92,65 +91,6 @@ class FogDriver < VmDriver
92
91
  raise "unimplemented"
93
92
  end
94
93
 
95
- =begin
96
-
97
- def run_command(command)
98
- ## vm_driver will need a little patching for this to work, as
99
- ## amis use keys for auth. i think it's just a matter of not passing the
100
- ## password to ssh_exec. So maybe the thing to do is have a ssh_key_exec
101
- ## function in vm_driver.rb that does the right thing.
102
-
103
- script_rand_name = rand(10000)
104
-
105
- if @os == "windows"
106
- local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.bat"
107
- remote_tempfile_path = "C:\\\\lab_script_#{script_rand_name}.bat"
108
- remote_run_command = remote_tempfile_path
109
- else
110
- local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
111
- remote_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
112
- remote_run_command = "/bin/sh #{remote_tempfile_path}"
113
- end
114
-
115
- # write out our script locally
116
- File.open(local_tempfile_path, 'w') {|f| f.write(command) }
117
-
118
- # since we can't copy easily w/o tools, let's just run it directly :/
119
- if @os == "linux"
120
- output_file = "/tmp/lab_command_output_#{rand(1000000)}"
121
-
122
- scp_to(local_tempfile_path, remote_tempfile_path)
123
- ssh_exec(remote_run_command + "> #{output_file}")
124
- scp_from(output_file, output_file)
125
- ssh_exec("rm #{output_file}")
126
- ssh_exec("rm #{remote_tempfile_path}")
127
-
128
- # Ghettohack!
129
- string = File.open(output_file,"r").read
130
- `rm #{output_file}`
131
-
132
- else
133
- raise "zomgwtfbbqnotools"
134
- end
135
- end
136
-
137
- def copy_from(from, to)
138
- raise "unimplemented"
139
- end
140
-
141
- def copy_to(from, to)
142
- raise "unimplemented"
143
- end
144
-
145
- def check_file_exists(file)
146
- raise "unimplemented"
147
- end
148
-
149
- def create_directory(directory)
150
- raise "unimplemented"
151
- end
152
- =end
153
-
154
94
  def cleanup
155
95
  @fog_server.destroy
156
96
  end
@@ -0,0 +1,120 @@
1
+ require 'vm_driver'
2
+
3
+ ##
4
+ ## $Id$
5
+ ##
6
+
7
+ # This driver was built against:
8
+ # VMware Vsphere 4.1
9
+
10
+ module Lab
11
+ module Drivers
12
+
13
+ class VsphereDriver < VmDriver
14
+
15
+ def initialize(config)
16
+ unless config['user'] then raise ArgumentError, "Must provide a username" end
17
+ unless config['host'] then raise ArgumentError, "Must provide a hostname" end
18
+ unless config[''] then raise ArgumentError, "Must provide a password" end
19
+ super(config)
20
+
21
+ @user = filter_command(config['user'])
22
+ @host = filter_command(config['host'])
23
+
24
+ # Soft dependency
25
+ begin
26
+ require 'rbvmomi'
27
+ rescue LoadError
28
+ raise "WARNING: Library rbvmomi not found. Could not create driver!"
29
+ end
30
+
31
+ vim = RbVmomi::VIM.connect host: @host, user: @user, password: @pass
32
+ dc = vim.serviceInstance.find_datacenter("datacenter1") or fail "datacenter not found"
33
+ @vm = dc.find_vm("test") or fail "VM not found"
34
+ end
35
+
36
+ def start
37
+ @vm.PowerOnVM_Task.wait_for_completion
38
+ end
39
+
40
+ def stop
41
+ @vm.PowerOffVM_Task.wait_for_completion
42
+ end
43
+
44
+ def suspend
45
+ @vm.SuspendVM_Task.wait_for_completion
46
+ end
47
+
48
+ def pause
49
+ raise "Unimplemented"
50
+ end
51
+
52
+ def resume
53
+ raise "Unimplemented"
54
+ end
55
+
56
+ def reset
57
+ @vm.ResetVM_Task.wait_for_completion
58
+ end
59
+
60
+ def create_snapshot(snapshot)
61
+ snapshot = filter_input(snapshot)
62
+ raise "Unimplemented"
63
+ end
64
+
65
+ def revert_snapshot(snapshot)
66
+ raise "Unimplemented"
67
+ # If we got here, the snapshot didn't exist
68
+ raise "Invalid Snapshot Name"
69
+ end
70
+
71
+ def delete_snapshot(snapshot, remove_children=false)
72
+ raise "Unimplemented"
73
+ # If we got here, the snapshot didn't exist
74
+ raise "Invalid Snapshot Name"
75
+ end
76
+
77
+ def delete_all_snapshots
78
+ raise "Unimplemented"
79
+ end
80
+
81
+ def run_command(command)
82
+ raise "Unimplemented"
83
+ end
84
+
85
+ def copy_from(from, to)
86
+ if @os == "linux"
87
+ scp_from(from, to)
88
+ else
89
+ raise "Unimplemented"
90
+ end
91
+ end
92
+
93
+ def copy_to(from, to)
94
+ if @os == "linux"
95
+ scp_to(from, to)
96
+ else
97
+ raise "Unimplemented"
98
+ end
99
+ end
100
+
101
+ def check_file_exists(file)
102
+ raise "Unimplemented"
103
+ end
104
+
105
+ def create_directory(directory)
106
+ raise "Unimplemented"
107
+ end
108
+
109
+ def cleanup
110
+ raise "Unimplemented"
111
+ end
112
+
113
+ def running?
114
+ raise "Unimplemented"
115
+ end
116
+
117
+ end
118
+
119
+ end
120
+ end
data/lib/lab/drivers.rb CHANGED
@@ -4,5 +4,6 @@ require 'driver/fog_driver'
4
4
  require 'driver/dynagen_driver'
5
5
  require 'driver/remote_workstation_driver'
6
6
  require 'driver/remote_esxi_driver'
7
+ require 'driver/vsphere_driver'
7
8
  #require 'driver/qemu_driver'
8
9
  #require 'driver/qemudo_driver'
@@ -0,0 +1,167 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
2
+
3
+ module Lab
4
+ module Modifier
5
+ module Meterpreter
6
+
7
+ end
8
+ end
9
+ end
10
+
11
+
12
+ # This allows us to override the default way of running commands
13
+ # Currently useful for the esx controller
14
+
15
+ module Lab
16
+ class Vm
17
+
18
+ attr_accessor :framework
19
+ attr_accessor :session
20
+ attr_accessor :session_input
21
+ attr_accessor :session_output
22
+
23
+ def create_framework
24
+ return if @framework
25
+ @framework = Msf::Simple::Framework.create
26
+ end
27
+
28
+ # perform the setup only once
29
+ def setup_session
30
+ return if @session
31
+
32
+ # require the framework (assumes this sits in lib/lab/modifiers)
33
+ require 'msf/base'
34
+
35
+ create_framework ## TODO - this should use a single framework
36
+ ## for all hosts, not one-per-host
37
+
38
+ @session = nil
39
+ @session_input = Rex::Ui::Text::Input::Buffer.new
40
+ @session_output = Rex::Ui::Text::Output::Buffer.new
41
+
42
+ if @os == "windows"
43
+ exploit_name = 'windows/smb/psexec'
44
+
45
+ # TODO - check for x86, choose the appropriate payload
46
+
47
+ payload_name = 'windows/meterpreter/bind_tcp'
48
+ options = { "RHOST" => @hostname,
49
+ "SMBUser" => @vm_user,
50
+ "SMBPass" => @vm_pass}
51
+
52
+ puts "DEBUG: using options #{options}"
53
+
54
+ # Initialize the exploit instance
55
+ exploit = @framework.exploits.create(exploit_name)
56
+
57
+ begin
58
+ # Fire it off.
59
+ @session = exploit.exploit_simple(
60
+ 'Payload' => payload_name,
61
+ 'Options' => options,
62
+ 'LocalInput' => @session_input,
63
+ 'LocalOutput' => @session_output)
64
+ @session.load_stdapi
65
+
66
+ puts "DEBUG: Generated session: #{@session}"
67
+
68
+ rescue Exception => e
69
+ puts "DEBUG: Unable to exploit"
70
+ puts e.to_s
71
+ end
72
+
73
+ else
74
+ module_name = 'scanner/ssh/ssh_login'
75
+
76
+ # TODO - check for x86, choose the appropriate payload
77
+
78
+ payload_name = 'linux/x86/shell_bind_tcp'
79
+ options = { "RHOSTS" => @hostname,
80
+ "USERNAME" => @vm_user,
81
+ "PASSWORD" => @vm_pass,
82
+ "BLANK_PASSWORDS" => false,
83
+ "USER_AS_PASS" => false,
84
+ "VERBOSE" => false}
85
+
86
+ puts "DEBUG: using options #{options}"
87
+
88
+ # Initialize the module instance
89
+ aux = @framework.auxiliary.create(module_name)
90
+
91
+ puts "DEBUG: created module: #{aux}"
92
+
93
+ begin
94
+ # Fire it off.
95
+ aux.run_simple(
96
+ 'Payload' => payload_name,
97
+ 'Options' => options,
98
+ 'LocalInput' => @session_input,
99
+ 'LocalOutput' => @session_output)
100
+
101
+ @session = @framework.sessions.first.last
102
+ puts "DEBUG: Generated session: #{@session}"
103
+ rescue Exception => e
104
+ puts "DEBUG: Unable to exploit"
105
+ puts e.to_s
106
+ end
107
+ end
108
+
109
+
110
+
111
+ end
112
+
113
+ def run_command(command, timeout=60)
114
+
115
+ setup_session
116
+ puts "Using session #{@session}"
117
+
118
+ # TODO: pass the timeout down
119
+
120
+ if @session
121
+ if @session.type == "shell"
122
+ puts "Running command via shell: #{command}"
123
+ @session.shell_command_token(command, timeout)
124
+ elsif @session.type == "meterpreter"
125
+ puts "Running command via meterpreter: #{command}"
126
+ @session.shell_command(command) #, timeout)
127
+ end
128
+ else
129
+ raise "No session"
130
+ end
131
+ end
132
+
133
+
134
+ # This isn't part of the normal API, but too good to pass up.
135
+ def run_script(script, options)
136
+ if @session.type == "meterpreter"
137
+ @session.execute_script(script, options)
138
+ else
139
+ raise "Unsupported on #{@session.type}"
140
+ end
141
+ end
142
+
143
+ # For meterpreter API compatibility
144
+ #def execute_file(script,options)
145
+ # run_script(script,options)
146
+ #end
147
+
148
+ def copy_to(local,remote)
149
+ setup_session
150
+ if @session.type == "meterpreter"
151
+ @session.run_cmd("upload #{local} #{remote}")
152
+ else
153
+ @driver.copy_to(local,remote)
154
+ end
155
+ end
156
+
157
+ def copy_from(local, remote)
158
+ setup_session
159
+ if @session.type == "meterpreter"
160
+ @session.run_cmd("download #{local} #{remote}")
161
+ else
162
+ @driver.copy_from(local,remote)
163
+ end
164
+ end
165
+
166
+ end
167
+ end
data/lib/lab/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lab
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.2"
3
3
  end
data/lib/lab/vm.rb CHANGED
@@ -7,28 +7,34 @@ class Vm
7
7
 
8
8
  attr_accessor :vmid
9
9
  attr_accessor :hostname
10
- attr_accessor :name
11
10
  attr_accessor :description
11
+ attr_accessor :user
12
+ attr_accessor :host
12
13
  attr_accessor :location
13
14
  attr_accessor :driver
14
15
  attr_accessor :credentials
15
16
  attr_accessor :tools
16
17
  attr_accessor :type
17
- attr_accessor :user
18
- attr_accessor :host
19
18
  attr_accessor :os
20
19
  attr_accessor :arch
20
+ attr_accessor :tags
21
21
 
22
22
  ## Initialize takes a vm configuration hash of the form
23
- ## - vmid (unique identifier)
24
- ## driver (vm technology)
23
+ ## - vmid (unique id)
24
+ ## hostname (unique name)
25
+ ## description (describes the vm's contents)
26
+ ## driver (vm driver)
27
+ ## location (if applicable - local system)
25
28
  ## user (if applicable - remote system)
26
29
  ## host (if applicable - remote system)
27
- ## pass (if applicable - remote system)
28
- ## location (file / uri)
30
+ ## pass (if applicable - remote system) # DISCOURAGED - USE KEYS!
31
+ ## tools (true if tools are installed)
32
+ ## type ( qa / vulnerable / etc - freeform option)
29
33
  ## credentials (of the form [ {'user'=>"user",'pass'=>"pass", 'admin' => false}, ... ])
30
- ## os (currently only linux / windows)
31
- ## arch (currently only 32 / 64
34
+ ## os (currently linux / windows / solaris / aix) - may be used in modifiers
35
+ ## arch (currently 32 / 64)
36
+ ## modifiers - can be anything in the modifiers directory
37
+ ## tags - list of strings associated with this vm
32
38
 
33
39
  def initialize(config = {})
34
40
 
@@ -48,7 +54,6 @@ class Vm
48
54
  @driver_type.downcase!
49
55
 
50
56
  @location = filter_input(config['location'])
51
- #@name = config['name'] || ""
52
57
  @description = config['description']
53
58
  @tools = config['tools']
54
59
  @os = config['os']
@@ -67,19 +72,19 @@ class Vm
67
72
  @user = filter_input(config['user']) || nil
68
73
  @host = filter_input(config['host']) || nil
69
74
  @port = filter_input(config['port']) || nil
70
- @pass = filter_input(config['pass']) || nil
75
+ @pass = filter_input(config['pass']) || nil # DISCORAGED, use keys!
71
76
 
72
- #Only dynagen systems need this
77
+ # Only dynagen systems need this
73
78
  @platform = config['platform']
74
79
 
75
- #Only fog systems need this
80
+ # Only fog systems need this
76
81
  @fog_config = config['fog_config']
77
82
 
78
- #puts "Passing driver config: #{config}"
79
-
80
83
  # Process the correct driver
81
84
  if @driver_type == "workstation"
82
85
  @driver = Lab::Drivers::WorkstationDriver.new(config)
86
+ elsif @driver_type == "remote_workstation"
87
+ @driver = Lab::Drivers::RemoteWorkstationDriver.new(config)
83
88
  elsif @driver_type == "virtualbox"
84
89
  @driver = Lab::Drivers::VirtualBoxDriver.new(config)
85
90
  elsif @driver_type == "fog"
@@ -88,8 +93,8 @@ class Vm
88
93
  @driver = Lab::Drivers::DynagenDriver.new(config, config['dynagen_config'])
89
94
  elsif @driver_type == "remote_esxi"
90
95
  @driver = Lab::Drivers::RemoteEsxiDriver.new(config)
91
- elsif @driver_type == "remote_workstation"
92
- @driver = Lab::Drivers::RemoteWorkstationDriver.new(config)
96
+ elsif @driver_type == "vsphere"
97
+ @driver = Lab::Drivers::VsphereDriver.new(config)
93
98
  #elsif @driver_type == "qemu"
94
99
  # @driver = Lab::Drivers::QemuDriver.new
95
100
  #elsif @driver_type == "qemudo"
@@ -110,8 +115,14 @@ class Vm
110
115
  @modifiers.each { |modifier| self.class.send(:include, eval("Lab::Modifier::#{modifier}"))}
111
116
  rescue Exception => e
112
117
  # modifier likely didn't exist
113
- end
118
+ end
114
119
  end
120
+
121
+ #
122
+ # Grab a tags array
123
+ #
124
+ @tags = config['tags']
125
+
115
126
  end
116
127
 
117
128
  def running?
@@ -205,7 +216,9 @@ class Vm
205
216
 
206
217
  # Standard configuration options
207
218
  out = " - vmid: #{@vmid}\n"
219
+ out += " hostname: #{@hostname}\n"
208
220
  out += " driver: #{@driver_type}\n"
221
+ out += " description: |\n #{@description}\n"
209
222
  out += " location: #{@location}\n"
210
223
  out += " type: #{@type}\n"
211
224
  out += " tools: #{@tools}\n"
@@ -215,6 +228,8 @@ class Vm
215
228
  if @user or @host # Remote vm/drivers only
216
229
  out += " user: #{@user}\n"
217
230
  out += " host: #{@host}\n"
231
+ out += " port: #{@port}\n"
232
+ out += " pass: #{@pass}\n"
218
233
  end
219
234
 
220
235
  if @platform
@@ -1,10 +1,10 @@
1
- ##
2
- ## $Id$
3
- ##
4
- ## This is the main lab controller. Require this controller to get all
5
- ## lab functionality.
6
- ##
7
- ##
1
+ #
2
+ # $Id$
3
+ #
4
+ # This is the main lab controller. Require this controller to get all
5
+ # lab functionality.
6
+ #
7
+ #
8
8
 
9
9
  $:.unshift(File.expand_path(File.dirname(__FILE__)))
10
10
  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), 'driver')))
@@ -29,16 +29,17 @@ module Controllers
29
29
  class VmController
30
30
 
31
31
  include Enumerable
32
- include Lab::Controllers::WorkstationController
32
+ include Lab::Controllers::WorkstationController
33
+ include Lab::Controllers::RemoteWorkstationController
33
34
  include Lab::Controllers::VirtualBoxController
34
35
  include Lab::Controllers::FogController
35
36
  include Lab::Controllers::DynagenController
36
37
  include Lab::Controllers::RemoteEsxiController
37
- include Lab::Controllers::RemoteWorkstationController
38
+ include Lab::Controllers::VsphereDriver
38
39
  #include Lab::Controllers::QemuController
39
40
  #include Lab::Controllers::QemudoController
40
41
  def initialize (labdef=nil)
41
-
42
+
42
43
  # Start with an empty array of vm objects
43
44
  @vms = []
44
45
 
@@ -59,23 +60,31 @@ module Controllers
59
60
  end
60
61
  end
61
62
 
62
- def find_by_vmid(vmid)
63
+ def find_by_vmid(search)
64
+ @vms.each do |vm|
65
+ return vm if vm.hostname.to_s.downcase == search.to_s.downcase
66
+ end
67
+ return nil
68
+ end
69
+
70
+ def find_by_tag(search)
63
71
  @vms.each do |vm|
64
- if (vm.hostname.to_s.downcase == vmid.to_s.downcase)
65
- return vm
72
+ vm.tags.each do |tag|
73
+ return vm if tag.downcase == search.to_s.downcase
66
74
  end
67
75
  end
68
76
  return nil
69
77
  end
70
78
 
71
- def add_vm(vmid, location=nil, os=nil, tools=nil, credentials=nil, user=nil, host=nil)
72
- @vms << Vm.new( {
79
+ def add_vm(vmid, location=nil, os=nil, tools=nil, credentials=nil, user=nil, host=nil)
80
+ @vms << Vm.new( {
73
81
  'vmid' => vmid,
74
82
  'driver' => type,
75
83
  'location' => location,
76
84
  'credentials' => credentials,
77
85
  'user' => user,
78
- 'host' => host} )
86
+ 'host' => host
87
+ })
79
88
  end
80
89
 
81
90
  def remove_by_vmid(vmid)
@@ -112,24 +121,30 @@ module Controllers
112
121
  false
113
122
  end
114
123
 
124
+ #
125
+ # Build a vm lab from a directory of files. Really only useful for file-based
126
+ # vm hosts. (vmware workstation)
127
+ #
115
128
  def build_from_dir(driver_type, dir, clear=false)
116
-
129
+
117
130
  if clear
118
131
  @vms = []
119
132
  end
120
133
 
121
134
  if driver_type.downcase == "workstation"
122
135
  vm_list = ::Lab::Controllers::WorkstationController::dir_list(dir)
136
+ elsif driver_type.downcase == "remote_workstation"
137
+ vm_list = ::Lab::Controllers::RemoteWorkstationController::dir_list(dir)
123
138
  elsif driver_type.downcase == "virtualbox"
124
139
  vm_list = ::Lab::Controllers::VirtualBoxController::dir_list(dir)
125
140
  elsif driver_type.downcase == "fog"
126
141
  vm_list = ::Lab::Controllers::FogController::dir_list(dir)
127
142
  elsif driver_type.downcase == "Dynagen"
128
143
  vm_list = ::Lab::Controllers::DynagenController::dir_list(dir)
129
- elsif driver_type.downcase == "remote_workstation"
130
- vm_list = ::Lab::Controllers::RemoteWorkstationController::dir_list(dir)
131
144
  elsif driver_type.downcase == "remote_esxi"
132
145
  vm_list =::Lab::Controllers::RemoteEsxiController::dir_list(dir)
146
+ elsif driver_type.downcase == "vsphere"
147
+ vm_list =::Lab::Controllers::VsphereController::dir_list(dir)
133
148
  else
134
149
  raise TypeError, "Unsupported VM Type"
135
150
  end
@@ -139,7 +154,12 @@ module Controllers
139
154
  end
140
155
  end
141
156
 
142
- def build_from_running(driver_type=nil, user=nil, host=nil, clear=false)
157
+
158
+ #
159
+ # Builds a vm lab from all running vms. Handy for connecting and saving out
160
+ # a config or just managing the currently running vms
161
+ #
162
+ def build_from_running(driver_type=nil, user=nil, host=nil, clear=false, pass=nil)
143
163
 
144
164
  if clear
145
165
  @vms = []
@@ -148,69 +168,77 @@ module Controllers
148
168
  case driver_type.intern
149
169
  when :workstation
150
170
  vm_list = ::Lab::Controllers::WorkstationController::running_list
151
-
152
171
  vm_list.each do |item|
153
-
154
- ## Name the VM
172
+ # Name the VM
155
173
  index = @vms.count + 1
156
-
157
- ## Add it to the vm list
158
- @vms << Vm.new( {
174
+ # Add it to the vm list
175
+ @vms << Vm.new({
176
+ 'vmid' => "vm_#{index}",
177
+ 'driver' => driver_type,
178
+ 'location' => item
179
+ })
180
+ end
181
+ when :remote_workstation
182
+ vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host)
183
+ vm_list.each do |item|
184
+ # Name the VM
185
+ index = @vms.count + 1
186
+ # Add it to the VM list
187
+ @vms << Vm.new({
159
188
  'vmid' => "vm_#{index}",
160
189
  'driver' => driver_type,
161
190
  'location' => item,
162
191
  'user' => user,
163
- 'host' => host } )
192
+ 'host' => host
193
+ })
164
194
  end
165
-
166
-
167
195
  when :virtualbox
168
196
  vm_list = ::Lab::Controllers::VirtualBoxController::running_list
169
197
  vm_list.each do |item|
170
- ## Add it to the vm list
198
+ # Add it to the vm list
171
199
  @vms << Vm.new( {
172
200
  'vmid' => "#{item}",
173
201
  'driver' => driver_type,
174
- 'location' => nil })
202
+ 'location' => nil
203
+ })
175
204
  end
176
205
  when :fog
177
- raise "Unsupported" # TODO - figure out a way to allow this
206
+ raise "Unsupported"
178
207
  when :dynagen
179
208
  raise "Unsupported"
180
- when :remote_workstation
181
- vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host)
182
-
209
+ when :remote_esxi
210
+ vm_list = ::Lab::Controllers::RemoteEsxiController::running_list(user,host)
183
211
  vm_list.each do |item|
184
-
185
- ## Name the VM
186
- index = @vms.count + 1
187
-
188
- ## Add it to the vm list
189
212
  @vms << Vm.new( {
190
- 'vmid' => "vm_#{index}",
213
+ 'vmid' => "#{item[:id]}",
214
+ 'name' => "#{item[:name]}",
191
215
  'driver' => driver_type,
192
- 'location' => item,
193
216
  'user' => user,
194
- 'host' => host } )
217
+ 'host' => host
218
+ })
195
219
  end
196
- when :remote_esxi
197
- vm_list = ::Lab::Controllers::RemoteEsxiController::running_list(user,host)
198
-
220
+ when :vsphere
221
+ vm_list = ::Lab::Controllers::VsphereController::running_list(user,host,pass)
199
222
  vm_list.each do |item|
200
223
  @vms << Vm.new( {
201
224
  'vmid' => "#{item[:id]}",
202
225
  'name' => "#{item[:name]}",
203
226
  'driver' => driver_type,
204
227
  'user' => user,
205
- 'host' => host } )
228
+ 'host' => host,
229
+ 'pass' => pass
230
+ })
206
231
  end
207
-
208
232
  else
209
233
  raise TypeError, "Unsupported VM Type"
210
234
  end
211
235
 
212
236
  end
213
237
 
238
+ #
239
+ # Applicable only to virtualbox. Reads the config file & parses / creates
240
+ # VM objects for each vm.
241
+ #
214
242
  def build_from_config(driver_type=nil, user=nil, host=nil, clear=false)
215
243
  if clear
216
244
  @vms = []
@@ -221,7 +249,7 @@ module Controllers
221
249
  vm_list = ::Lab::Controllers::VirtualBoxController::config_list
222
250
 
223
251
  vm_list.each do |item|
224
- ## Add it to the vm list
252
+ # Add it to the vm list
225
253
  @vms << Vm.new( {
226
254
  'vmid' => "#{item}",
227
255
  'driver' => driver_type,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-02 00:00:00.000000000 Z
12
+ date: 2012-04-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &14248700 !ruby/object:Gem::Requirement
16
+ requirement: &21345740 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *14248700
24
+ version_requirements: *21345740
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: net-ssh
27
- requirement: &14247980 !ruby/object:Gem::Requirement
27
+ requirement: &21329820 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *14247980
35
+ version_requirements: *21329820
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: net-scp
38
- requirement: &14229460 !ruby/object:Gem::Requirement
38
+ requirement: &21328760 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *14229460
46
+ version_requirements: *21328760
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rbvmomi
49
- requirement: &14228480 !ruby/object:Gem::Requirement
49
+ requirement: &21328000 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *14228480
57
+ version_requirements: *21328000
58
58
  description: ! 'Start/Stop/Revert and do other cool stuff w/ Vmware, Virtualbox, and
59
59
  ESXi vms. This gem wraps common CLI utilities and other gems to create a common
60
60
  inteface for vms. '
@@ -76,10 +76,10 @@ files:
76
76
  - lib/lab.rb
77
77
  - lib/lab/controller/dynagen_controller.rb
78
78
  - lib/lab/controller/fog_controller.rb
79
- - lib/lab/controller/remote_esx_controller.rb
80
79
  - lib/lab/controller/remote_esxi_controller.rb
81
80
  - lib/lab/controller/remote_workstation_controller.rb
82
81
  - lib/lab/controller/virtualbox_controller.rb
82
+ - lib/lab/controller/vsphere_controller.rb
83
83
  - lib/lab/controller/workstation_controller.rb
84
84
  - lib/lab/controller/workstation_vixr_controller.rb
85
85
  - lib/lab/controllers.rb
@@ -89,18 +89,19 @@ files:
89
89
  - lib/lab/driver/remote_workstation_driver.rb
90
90
  - lib/lab/driver/virtualbox_driver.rb
91
91
  - lib/lab/driver/vm_driver.rb
92
+ - lib/lab/driver/vsphere_driver.rb
92
93
  - lib/lab/driver/workstation_driver.rb
93
94
  - lib/lab/driver/workstation_vixr_driver.rb
94
95
  - lib/lab/drivers.rb
95
96
  - lib/lab/modifier/backtrack5_modifier.rb
96
97
  - lib/lab/modifier/dos_modifier.rb
98
+ - lib/lab/modifier/meterpreter_modifier.rb
97
99
  - lib/lab/modifier/test_modifier.rb
98
100
  - lib/lab/modifiers.rb
99
101
  - lib/lab/version.rb
100
102
  - lib/lab/vm.rb
101
103
  - lib/lab/vm_controller.rb
102
104
  - src/Gemfile
103
- - src/README.md
104
105
  - src/Rakefile
105
106
  - src/TODO
106
107
  - src/config/test_lab.yml
data/src/README.md DELETED
@@ -1,80 +0,0 @@
1
- This folder contains the libraries necessary to run the lab plugin, and can also be used in a standalone way to automate virtual machines.
2
-
3
- CONCEPTS:
4
- =========
5
-
6
- The lab provides a clean interface to common vm functions such as start / stop / snapshot / revert and even running system commands or higher-level functions like opening a browser to a specified URL. It's designed so the different VM technologies have a similiar 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 software (such as start/stop/revert), and controllers implement the commands which apply to all vms (such as listing all running vms, or cloning a vm).
7
-
8
- If you're interested in porting a vm software (see below), please take a look at the workstation_driver.rb and the workstation_controller.rb -- This is a simple driver / controller in the lab, and you can simply copy / modify this to implement a new driver & controller for the software.
9
-
10
- SUPPORTED VM TECHNOLOGIES:
11
- ==========================
12
- NOTE: The lab libraries have only been tested with linux as a host, porting to windows is not planned at this time.
13
-
14
- Implemented:
15
- - workstation (Tested against 7.x)
16
- - remote_workstation (Tested against 7.x)
17
- - virtualbox (Tested against 4.x)
18
- - remote_esx (VMware ESX Host Agent 4.1.0 build-348481)
19
-
20
- Partially Implemented:
21
- - amazon_ec2 (via fog gem)
22
- - dynagen
23
-
24
- Need Implementation:
25
- - qemu
26
- - qemudo
27
- - others?
28
-
29
- PLATFORM SUPPORT:
30
- =================
31
- 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).
32
-
33
- Platform Dependencies:
34
- - whatever vm software is necessary for the driver you're using (see SUPPORTED VM TECHNOLOGIES above)
35
- - 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.
36
- - fog - require to use the amazon_ec2 driver
37
-
38
- STANDALONE API:
39
- ===============
40
- BACKGROUND:
41
-
42
- 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.
43
-
44
- USAGE:
45
-
46
- You must first create a yaml file which describes your vm. See data/lab/test_targets.yml for an example.
47
- <pre>
48
- require 'vm_controller'
49
- vm_controller = ::Lab::Controllers::VmController.new(YAML.load_file(lab_def))
50
- vm_controller['vm1'].start
51
- vm_controller['vm1'].snapshot("clean")
52
- vm_controller['vm1'].run_command("rm /etc/resolv.conf")
53
- vm_controller['vm1'].open_uri("http://autopwn:8080")
54
- vm_controller['vm1'].revert("clean")
55
- vm_controller['vm1'].revert("clean")
56
- </pre>
57
- METASPLOIT MSFCONSOLE LAB PLUGIN:
58
- =================================
59
-
60
- BACKGROUND:
61
-
62
- 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.
63
-
64
- USAGE:
65
-
66
- Here's some example usage for the lab plugin.
67
- <pre>
68
- msf> load lab // Loads the lab plugin
69
- msf> lab_load <path_to_lab_file> // Loads from a lab configuration file. See data/lab/test_targets.yml for an example
70
- msf> lab_load_dir workstation /path/to/vmx/files // Loads from a local directory.
71
- msf> lab_load_running remote_esx root esx_server // Loads all running vms.
72
- msf> lab_start vm1 // Start a vm which was loaded above
73
- msf> lab_snapshot vm1 snapshot_1 // Snapshot a vm as 'snapshot_1'
74
- msf> lab_run_command ("rm -rf /") // oops!
75
- msf> lab_show // Show all vms that we're aware of
76
- msf> lab_show_running // Show only running vms
77
- msf> lab_start vm2 // Start another vm
78
- msf> lab_suspend vm1 // Suspend a vm
79
- msf> lab_revert all snapshot_1 // Revert all vms back to 'snapshot_1'
80
- </pre>