lab 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -0
- data/Gemfile.lock +16 -0
- data/README +77 -0
- data/Rakefile +1 -0
- data/TODO +15 -0
- data/lab.gemspec +24 -0
- data/lib/lab.rb +4 -0
- data/lib/lab/controller/dynagen_controller.rb +14 -0
- data/lib/lab/controller/fog_controller.rb +6 -0
- data/lib/lab/controller/remote_esx_controller.rb +62 -0
- data/lib/lab/controller/remote_workstation_controller.rb +22 -0
- data/lib/lab/controller/virtualbox_controller.rb +25 -0
- data/lib/lab/controller/workstation_controller.rb +17 -0
- data/lib/lab/controller/workstation_vixr_controller.rb +19 -0
- data/lib/lab/controllers.rb +10 -0
- data/lib/lab/driver/dynagen_driver.rb +47 -0
- data/lib/lab/driver/fog_driver.rb +164 -0
- data/lib/lab/driver/remote_esx_driver.rb +177 -0
- data/lib/lab/driver/remote_workstation_driver.rb +198 -0
- data/lib/lab/driver/virtualbox_driver.rb +142 -0
- data/lib/lab/driver/vm_driver.rb +180 -0
- data/lib/lab/driver/workstation_driver.rb +188 -0
- data/lib/lab/driver/workstation_vixr_driver.rb +126 -0
- data/lib/lab/drivers.rb +8 -0
- data/lib/lab/modifier/backtrack5_modifier.rb +16 -0
- data/lib/lab/modifier/dos_modifier.rb +14 -0
- data/lib/lab/modifier/meterpreter_modifier.rb +167 -0
- data/lib/lab/modifier/test_modifier.rb +16 -0
- data/lib/lab/modifiers.rb +4 -0
- data/lib/lab/version.rb +3 -0
- data/lib/lab/vm.rb +253 -0
- data/lib/lab/vm_controller.rb +238 -0
- data/test/.gitkeep +0 -0
- metadata +39 -6
@@ -0,0 +1,180 @@
|
|
1
|
+
##
|
2
|
+
## $Id$
|
3
|
+
##
|
4
|
+
|
5
|
+
#
|
6
|
+
# !!WARNING!! - All drivers are expected to filter input before running
|
7
|
+
# anything based on it. This is particularly important in the case
|
8
|
+
# of the drivers which wrap a command line to provide functionality.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Lab
|
12
|
+
module Drivers
|
13
|
+
class VmDriver
|
14
|
+
|
15
|
+
attr_accessor :vmid
|
16
|
+
attr_accessor :location
|
17
|
+
attr_accessor :os
|
18
|
+
attr_accessor :tools
|
19
|
+
attr_accessor :credentials
|
20
|
+
|
21
|
+
def initialize(config)
|
22
|
+
|
23
|
+
@vmid = filter_command(config["vmid"].to_s)
|
24
|
+
@location = filter_command(config["location"])
|
25
|
+
@credentials = config["credentials"] || []
|
26
|
+
@tools = filter_input(config["tools"])
|
27
|
+
@os = filter_input(config["os"])
|
28
|
+
@hostname = filter_input(config["hostname"]) || filter_input(config["vmid"].to_s)
|
29
|
+
|
30
|
+
# Currently only implemented for the first set
|
31
|
+
if @credentials.count > 0
|
32
|
+
@vm_user = filter_input(@credentials[0]['user'])
|
33
|
+
@vm_pass = filter_input(@credentials[0]['pass'])
|
34
|
+
@vm_keyfile = filter_input(@credentials[0]['keyfile'])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
## This interface must be implemented in a child driver class
|
39
|
+
## #########################################################
|
40
|
+
|
41
|
+
def register
|
42
|
+
raise "Command not Implemented"
|
43
|
+
end
|
44
|
+
|
45
|
+
def unregister
|
46
|
+
raise "Command not Implemented"
|
47
|
+
end
|
48
|
+
|
49
|
+
def start
|
50
|
+
raise "Command not Implemented"
|
51
|
+
end
|
52
|
+
|
53
|
+
def stop
|
54
|
+
raise "Command not Implemented"
|
55
|
+
end
|
56
|
+
|
57
|
+
def suspend
|
58
|
+
raise "Command not Implemented"
|
59
|
+
end
|
60
|
+
|
61
|
+
def pause
|
62
|
+
raise "Command not Implemented"
|
63
|
+
end
|
64
|
+
|
65
|
+
def resume
|
66
|
+
raise "Command not Implemented"
|
67
|
+
end
|
68
|
+
|
69
|
+
def reset
|
70
|
+
raise "Command not Implemented"
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_snapshot(snapshot)
|
74
|
+
raise "Command not Implemented"
|
75
|
+
end
|
76
|
+
|
77
|
+
def revert_snapshot(snapshot)
|
78
|
+
raise "Command not Implemented"
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_snapshot(snapshot)
|
82
|
+
raise "Command not Implemented"
|
83
|
+
end
|
84
|
+
|
85
|
+
def run_command(command)
|
86
|
+
raise "Command not Implemented"
|
87
|
+
end
|
88
|
+
|
89
|
+
def copy_from(from, to)
|
90
|
+
raise "Command not Implemented"
|
91
|
+
end
|
92
|
+
|
93
|
+
def copy_to(from, to)
|
94
|
+
raise "Command not Implemented"
|
95
|
+
end
|
96
|
+
|
97
|
+
def check_file_exists(file)
|
98
|
+
raise "Command not Implemented"
|
99
|
+
end
|
100
|
+
|
101
|
+
def create_directory(directory)
|
102
|
+
raise "Command not Implemented"
|
103
|
+
end
|
104
|
+
|
105
|
+
def cleanup
|
106
|
+
raise "Command not Implemented"
|
107
|
+
end
|
108
|
+
|
109
|
+
## End Interface
|
110
|
+
## #########################################################
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def scp_to(local,remote)
|
115
|
+
#require 'net/scp'
|
116
|
+
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
|
117
|
+
# scp.upload!(from,to)
|
118
|
+
#end
|
119
|
+
|
120
|
+
system_command("scp #{local} #{@vm_user}@#{@hostname}:#{remote}")
|
121
|
+
end
|
122
|
+
|
123
|
+
def scp_from(local,remote)
|
124
|
+
#require 'net/scp'
|
125
|
+
# download a file from a remote server
|
126
|
+
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
|
127
|
+
# scp.download!(from,to)
|
128
|
+
#end
|
129
|
+
|
130
|
+
system_command("scp #{@vm_user}@#{@hostname}:#{remote} #{local}")
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
def ssh_exec(command)
|
135
|
+
|
136
|
+
::Net::SSH.start(@hostname, @vm_user, :password => @vm_pass) do |ssh|
|
137
|
+
result = ssh.exec!(command)
|
138
|
+
end
|
139
|
+
|
140
|
+
`scp #{@vm_user}@#{@hostname} from to`
|
141
|
+
end
|
142
|
+
|
143
|
+
def filter_input(string)
|
144
|
+
return "" unless string # nil becomes empty string
|
145
|
+
return unless string.class == String # Allow other types unmodified
|
146
|
+
|
147
|
+
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
|
148
|
+
raise "WARNING! Invalid character in: #{string}"
|
149
|
+
end
|
150
|
+
|
151
|
+
string
|
152
|
+
end
|
153
|
+
|
154
|
+
def filter_command(string)
|
155
|
+
return "" unless string # nil becomes empty string
|
156
|
+
return unless string.class == String # Allow other types unmodified
|
157
|
+
|
158
|
+
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
|
159
|
+
raise "WARNING! Invalid character in: #{string}"
|
160
|
+
end
|
161
|
+
|
162
|
+
string
|
163
|
+
end
|
164
|
+
|
165
|
+
# The only reason we don't filter here is because we need
|
166
|
+
# the ability to still run clean (controlled entirely by us)
|
167
|
+
# command lines.
|
168
|
+
def system_command(command)
|
169
|
+
#puts "DEBUG: system command #{command}"
|
170
|
+
system(command)
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def remote_system_command(command)
|
175
|
+
system_command("ssh #{@user}@#{@host} \"#{command}\"")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'vm_driver'
|
2
|
+
|
3
|
+
##
|
4
|
+
## $Id$
|
5
|
+
##
|
6
|
+
|
7
|
+
module Lab
|
8
|
+
module Drivers
|
9
|
+
|
10
|
+
class WorkstationDriver < VmDriver
|
11
|
+
|
12
|
+
def initialize(config)
|
13
|
+
super(config)
|
14
|
+
|
15
|
+
if !File.exist?(@location)
|
16
|
+
raise ArgumentError,"Couldn't find: #{@location}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
system_command("vmrun -T ws start " + "\'#{@location}\' nogui")
|
22
|
+
end
|
23
|
+
|
24
|
+
def stop
|
25
|
+
system_command("vmrun -T ws stop " + "\'#{@location}\' nogui")
|
26
|
+
end
|
27
|
+
|
28
|
+
def suspend
|
29
|
+
system_command("vmrun -T ws suspend " + "\'#{@location}\' nogui")
|
30
|
+
end
|
31
|
+
|
32
|
+
def pause
|
33
|
+
system_command("vmrun -T ws pause " + "\'#{@location}\' nogui")
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset
|
37
|
+
system_command("vmrun -T ws reset " + "\'#{@location}\' nogui")
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_snapshot(snapshot)
|
41
|
+
snapshot = filter_input(snapshot)
|
42
|
+
system_command("vmrun -T ws snapshot " + "\'#{@location}\' \'#{snapshot}\' nogui")
|
43
|
+
end
|
44
|
+
|
45
|
+
def revert_snapshot(snapshot)
|
46
|
+
snapshot = filter_input(snapshot)
|
47
|
+
system_command("vmrun -T ws revertToSnapshot " + "\'#{@location}\' \'#{snapshot}\' nogui")
|
48
|
+
end
|
49
|
+
|
50
|
+
def delete_snapshot(snapshot)
|
51
|
+
snapshot = filter_input(snapshot)
|
52
|
+
system_command("vmrun -T ws deleteSnapshot " + "\'#{@location}\' \'#{snapshot}\' nogui" )
|
53
|
+
end
|
54
|
+
|
55
|
+
def run_command(command)
|
56
|
+
|
57
|
+
script_rand_name = rand(10000)
|
58
|
+
|
59
|
+
if @os == "windows"
|
60
|
+
local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.bat"
|
61
|
+
remote_tempfile_path = "C:\\\\lab_script_#{script_rand_name}.bat"
|
62
|
+
remote_run_command = remote_tempfile_path
|
63
|
+
else
|
64
|
+
local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
|
65
|
+
remote_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
|
66
|
+
remote_run_command = "/bin/sh #{remote_tempfile_path}"
|
67
|
+
end
|
68
|
+
|
69
|
+
# write out our script locally
|
70
|
+
File.open(local_tempfile_path, 'w') {|f| f.write(command) }
|
71
|
+
|
72
|
+
# we really can't filter command, so we're gonna stick it in a script
|
73
|
+
if @tools
|
74
|
+
# copy our local tempfile to the guest
|
75
|
+
vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
|
76
|
+
"copyFileFromHostToGuest \'#{@location}\' \'#{local_tempfile_path}\'" +
|
77
|
+
" \'#{remote_tempfile_path}\' nogui"
|
78
|
+
system_command(vmrunstr)
|
79
|
+
|
80
|
+
# now run it on the guest
|
81
|
+
vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
|
82
|
+
"runProgramInGuest \'#{@location}\' -noWait -activeWindow \'#{remote_run_command}\'"
|
83
|
+
system_command(vmrunstr)
|
84
|
+
|
85
|
+
## CLEANUP
|
86
|
+
# delete it on the guest
|
87
|
+
vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
|
88
|
+
"deleteFileInGuest \'#{@location}\' \'#{remote_tempfile_path}\'"
|
89
|
+
system_command(vmrunstr)
|
90
|
+
|
91
|
+
# delete it locally
|
92
|
+
local_delete_command = "rm #{local_tempfile_path}"
|
93
|
+
system_command(local_delete_command)
|
94
|
+
else
|
95
|
+
# since we can't copy easily w/o tools, let's just run it directly :/
|
96
|
+
if @os == "linux"
|
97
|
+
|
98
|
+
output_file = "/tmp/lab_command_output_#{rand(1000000)}"
|
99
|
+
|
100
|
+
scp_to(local_tempfile_path, remote_tempfile_path)
|
101
|
+
ssh_exec(remote_run_command + "> #{output_file}")
|
102
|
+
scp_from(output_file, output_file)
|
103
|
+
|
104
|
+
ssh_exec("rm #{output_file}")
|
105
|
+
ssh_exec("rm #{remote_tempfile_path}")
|
106
|
+
|
107
|
+
# Ghettohack!
|
108
|
+
string = File.open(output_file,"r").read
|
109
|
+
`rm #{output_file}`
|
110
|
+
|
111
|
+
else
|
112
|
+
raise "zomgwtfbbqnotools"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
return string
|
116
|
+
end
|
117
|
+
|
118
|
+
def copy_from(from, to)
|
119
|
+
from = filter_input(from)
|
120
|
+
to = filter_input(to)
|
121
|
+
if @tools
|
122
|
+
vmrunstr = "vmrun -T ws -gu \'#{@vm_user}\' -gp \'#{@vm_pass}\' copyFileFromGuestToHost " +
|
123
|
+
"\'#{@location}\' \'#{from}\' \'#{to}\'"
|
124
|
+
else
|
125
|
+
scp_from(from, to)
|
126
|
+
end
|
127
|
+
system_command(vmrunstr)
|
128
|
+
end
|
129
|
+
|
130
|
+
def copy_to(from, to)
|
131
|
+
from = filter_input(from)
|
132
|
+
to = filter_input(to)
|
133
|
+
if @tools
|
134
|
+
vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} copyFileFromHostToGuest " +
|
135
|
+
"\'#{@location}\' \'#{from}\' \'#{to}\'"
|
136
|
+
system_command(vmrunstr)
|
137
|
+
else
|
138
|
+
scp_to(from, to)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def check_file_exists(file)
|
143
|
+
file = filter_input(file)
|
144
|
+
if @tools
|
145
|
+
vmrunstr = "vmrun -T ws -gu \'#{@vm_user}\' -gp \'#{@vm_pass}\' fileExistsInGuest " +
|
146
|
+
"\'#{@location}\' \'#{file}\' "
|
147
|
+
system_command(vmrunstr)
|
148
|
+
else
|
149
|
+
raise "Unsupported"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def create_directory(directory)
|
154
|
+
directory = filter_input(directory)
|
155
|
+
if @tools
|
156
|
+
vmrunstr = "vmrun -T ws -gu \'#{@vm_user}\' -gp \'#{@vm_pass}\' createDirectoryInGuest " +
|
157
|
+
" \'#{@location}\' \'#{directory}\' "
|
158
|
+
system_command(vmrunstr)
|
159
|
+
else
|
160
|
+
raise "Unsupported"
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
def cleanup
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
def running?
|
171
|
+
## Get running Vms
|
172
|
+
running = `vmrun list`
|
173
|
+
running_array = running.split("\n")
|
174
|
+
running_array.shift
|
175
|
+
|
176
|
+
running_array.each do |vmx|
|
177
|
+
if vmx.to_s == @location.to_s
|
178
|
+
return true
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
return false
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'vm_driver'
|
2
|
+
##
|
3
|
+
## $Id$
|
4
|
+
##
|
5
|
+
|
6
|
+
# This requires rhythmx's vixr driver from https://github.com/rhythmx/vixr
|
7
|
+
# and below that, the VIX api from vmware http://www.vmware.com/support/developer/vix-api/
|
8
|
+
|
9
|
+
module Lab
|
10
|
+
module Drivers
|
11
|
+
|
12
|
+
class WorkstationVixrDriver < VmDriver
|
13
|
+
|
14
|
+
attr_accessor :type
|
15
|
+
attr_accessor :location
|
16
|
+
|
17
|
+
def initialize(vmid, location, os=nil, tools=false, credentials=nil)
|
18
|
+
|
19
|
+
# We have to treat this differently, as it's not in the same tree
|
20
|
+
begin
|
21
|
+
require 'vixr'
|
22
|
+
rescue LoadError
|
23
|
+
puts "WARNING: Library pro_vixr not found. To resolve this error, please\n" +
|
24
|
+
" install the vixr gem. Latest is available here:\n" +
|
25
|
+
"https://github.com/rhythmx/vixr ."
|
26
|
+
raise "Unable to create vixr driver"
|
27
|
+
end
|
28
|
+
|
29
|
+
@vmid = filter_command(vmid)
|
30
|
+
@location = filter_command(location)
|
31
|
+
|
32
|
+
if !File.exist?(@location)
|
33
|
+
raise ArgumentError,"Couldn't find: " + location
|
34
|
+
end
|
35
|
+
|
36
|
+
@credentials = credentials
|
37
|
+
@tools = tools # not used in command lines, no filter
|
38
|
+
@os = os # not used in command lines, no filter
|
39
|
+
|
40
|
+
# TODO - Currently only implemented for the first set
|
41
|
+
if @credentials.count > 0
|
42
|
+
@vm_user = filter_input(@credentials[0]['user']) || "\'\'"
|
43
|
+
@vm_pass = filter_input(@credentials[0]['pass']) || "\'\'"
|
44
|
+
end
|
45
|
+
|
46
|
+
host = VixR.connect()
|
47
|
+
vm = host.open_vmx(@location)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def start
|
52
|
+
vm.power_on
|
53
|
+
end
|
54
|
+
|
55
|
+
def stop
|
56
|
+
vm.power_off
|
57
|
+
end
|
58
|
+
|
59
|
+
def suspend
|
60
|
+
vm.suspend
|
61
|
+
end
|
62
|
+
|
63
|
+
def pause
|
64
|
+
vm.pause
|
65
|
+
end
|
66
|
+
|
67
|
+
def reset
|
68
|
+
vm.reset
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_snapshot(snapshot)
|
72
|
+
snapshot = filter_input(snapshot)
|
73
|
+
system_command("ssh #{@user}@#{@host} vmrun -T ws snapshot \\\'#{@location}\\\' #{snapshot} nogui")
|
74
|
+
end
|
75
|
+
|
76
|
+
def revert_snapshot(snapshot)
|
77
|
+
snapshot = filter_input(snapshot)
|
78
|
+
system_command("ssh #{@user}@#{@host} vmrun -T ws revertToSnapshot \\\'#{@location}\\\' #{snapshot} nogui")
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_snapshot(snapshot)
|
82
|
+
snapshot = filter_input(snapshot)
|
83
|
+
system_command("ssh #{@user}@#{@host} vmrun -T ws deleteSnapshot \\\'#{@location}\\\' #{snapshot} nogui" )
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def run_command(command)
|
88
|
+
command = filter_input(command)
|
89
|
+
if vm.login(@vm_user,@vm_pass)
|
90
|
+
vm.run_prog(command)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def copy_from(from, to)
|
95
|
+
from = filter_input(from)
|
96
|
+
to = filter_input(to)
|
97
|
+
cp_from_host(from,to)
|
98
|
+
end
|
99
|
+
|
100
|
+
def copy_to(from, to)
|
101
|
+
from = filter_input(from)
|
102
|
+
to = filter_input(to)
|
103
|
+
vm.cp_to_guest(from,to)
|
104
|
+
end
|
105
|
+
|
106
|
+
def check_file_exists(file)
|
107
|
+
file = filter_input(file)
|
108
|
+
file_exists?(file)
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_directory(directory)
|
112
|
+
directory = filter_input(directory)
|
113
|
+
end
|
114
|
+
|
115
|
+
def cleanup
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
def running?
|
120
|
+
vm.running?
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|