Class: Lab::Vm

Inherits:
Object
  • Object
show all
Defined in:
lib/lab/vm.rb,
lib/lab/modifier/meterpreter_modifier.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ Vm

Returns a new instance of Vm.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/lab/vm.rb', line 42

def initialize(config = {})  

  # TODO - This is a mess. clean up, and pass stuff down to drivers
  # and then rework the code that uses this api. 
  @vmid = config['vmid'].to_s 
  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.downcase!

  @location = filter_input(config['location'])
  @description = config['description']
  @tools = config['tools']
  @os = config['os']
  @arch = config['arch']
  @type = filter_input(config['type']) || "unspecified"
  @credentials = config['credentials'] || []
  
  # 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

  # Only applicable to remote systems
  @user = filter_input(config['user']) || nil
  @host = filter_input(config['host']) || nil
  @port = filter_input(config['port']) || nil
  @pass = filter_input(config['pass']) || nil # DISCORAGED, use keys!

  # Only dynagen systems need this
  @platform = config['platform']

  # Only fog systems need this
  @fog_config = config['fog_config']

  # Process the correct driver
  if @driver_type == "workstation"
    @driver = Lab::Drivers::WorkstationDriver.new(config)
  elsif @driver_type == "remote_workstation"
    @driver = Lab::Drivers::RemoteWorkstationDriver.new(config)
  elsif @driver_type == "virtualbox"
    @driver = Lab::Drivers::VirtualBoxDriver.new(config)
  elsif @driver_type == "fog"
    @driver = Lab::Drivers::FogDriver.new(config, config['fog_config'])
  elsif @driver_type == "dynagen"
    @driver = Lab::Drivers::DynagenDriver.new(config, config['dynagen_config'])  
  elsif @driver_type == "remote_esxi"
    @driver = Lab::Drivers::RemoteEsxiDriver.new(config)
  elsif @driver_type == "vsphere"
    @driver = Lab::Drivers::VsphereDriver.new(config)
  #elsif @driver_type == "qemu"
  #  @driver = Lab::Drivers::QemuDriver.new
  #elsif @driver_type == "qemudo"
  #  @driver = Lab::Drivers::QemudoDriver.new
  else
    raise "Unknown Driver Type"
  end
      
  # Load in a list of modifiers. These provide additional methods
  # Currently it is up to the user to verify that 
  # modifiers are properly used with the correct VM image.
  #
  # If not, the results are likely to be disasterous.
  @modifiers = config['modifiers']
  
  if @modifiers  
    begin
       @modifiers.each { |modifier|  self.class.send(:include, eval("Lab::Modifier::#{modifier}"))}
    rescue Exception => e
      # modifier likely didn't exist
    end
  end
  
  #
  # Grab a list of snapshots & tags associated with this machine
  #
  #   machine_tags:
  #   - ie6
  #   - ie7
  #   - ie8
  #   - firefox
  #   snapshots:
  #   - ie6:
  #    - snapshot_tags:
  #     - ie6
  #   - ie7:
  #    - snapshot_tags:
  #     - ie7
  #     - ie8:
  #    - snapshot_tags:
  #     - ie8
  #   - bap:
  #    - snapshot_tags:
  #     - flash_10.2.153.1
  #     - reader_9.3.3
  #     - java_6u23
  #     - quicktime_player_7.6.9
  #
  @machine_tags = config['machine_tags']
  @snapshots = config['snapshots']

end

Instance Attribute Details

#archObject

Returns the value of attribute arch.



19
20
21
# File 'lib/lab/vm.rb', line 19

def arch
  @arch
end

#credentialsObject

Returns the value of attribute credentials.



15
16
17
# File 'lib/lab/vm.rb', line 15

def credentials
  @credentials
end

#descriptionObject

Returns the value of attribute description.



10
11
12
# File 'lib/lab/vm.rb', line 10

def description
  @description
end

#driverObject

Returns the value of attribute driver.



14
15
16
# File 'lib/lab/vm.rb', line 14

def driver
  @driver
end

#frameworkObject

Returns the value of attribute framework.



18
19
20
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 18

def framework
  @framework
end

#hostObject

Returns the value of attribute host.



12
13
14
# File 'lib/lab/vm.rb', line 12

def host
  @host
end

#hostnameObject

Returns the value of attribute hostname.



9
10
11
# File 'lib/lab/vm.rb', line 9

def hostname
  @hostname
end

#locationObject

Returns the value of attribute location.



13
14
15
# File 'lib/lab/vm.rb', line 13

def location
  @location
end

#machine_tagsObject

Returns the value of attribute machine_tags.



20
21
22
# File 'lib/lab/vm.rb', line 20

def machine_tags
  @machine_tags
end

#osObject

Returns the value of attribute os.



18
19
20
# File 'lib/lab/vm.rb', line 18

def os
  @os
end

#sessionObject

Returns the value of attribute session.



19
20
21
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 19

def session
  @session
end

#session_inputObject

Returns the value of attribute session_input.



20
21
22
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 20

def session_input
  @session_input
end

#session_outputObject

Returns the value of attribute session_output.



21
22
23
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 21

def session_output
  @session_output
end

#snapshotsObject

Returns the value of attribute snapshots.



21
22
23
# File 'lib/lab/vm.rb', line 21

def snapshots
  @snapshots
end

#toolsObject

Returns the value of attribute tools.



16
17
18
# File 'lib/lab/vm.rb', line 16

def tools
  @tools
end

#typeObject

Returns the value of attribute type.



17
18
19
# File 'lib/lab/vm.rb', line 17

def type
  @type
end

#userObject

Returns the value of attribute user.



11
12
13
# File 'lib/lab/vm.rb', line 11

def user
  @user
end

#vmidObject

Returns the value of attribute vmid.



8
9
10
# File 'lib/lab/vm.rb', line 8

def vmid
  @vmid
end

Instance Method Details

#check_file_exists(file) ⇒ Object



215
216
217
# File 'lib/lab/vm.rb', line 215

def check_file_exists(file)
  @driver.check_file_exists(file)
end

#copy_from(local, remote) ⇒ Object



207
208
209
# File 'lib/lab/vm.rb', line 207

def copy_from(from,to)
  @driver.copy_from(from,to)
end

#copy_to(local, remote) ⇒ Object

For meterpreter API compatibility def execute_file(script,options) run_script(script,options) end



148
149
150
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 148

def copy_to(from,to)
  @driver.copy_to(from,to)
end

#create_directory(directory) ⇒ Object



219
220
221
# File 'lib/lab/vm.rb', line 219

def create_directory(directory)
  @driver.create_directory(directory)
end

#create_frameworkObject



23
24
25
26
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 23

def create_framework
	return if @framework
	@framework    = Msf::Simple::Framework.create
end

#create_snapshot(snapshot) ⇒ Object



186
187
188
# File 'lib/lab/vm.rb', line 186

def create_snapshot(snapshot)
  @driver.create_snapshot(snapshot)
end

#delete_snapshot(snapshot) ⇒ Object



194
195
196
# File 'lib/lab/vm.rb', line 194

def delete_snapshot(snapshot)
  @driver.delete_snapshot(snapshot)
end

#open_uri(uri) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
# File 'lib/lab/vm.rb', line 223

def open_uri(uri)
  # we don't filter the uri, as it's getting tossed into a script 
  # by the driver
  if @os == "windows"
    command = "\"C:\\program files\\internet explorer\\iexplore.exe\" #{uri}"
  else
    command = "firefox #{uri}"
  end

  @driver.run_command(command)
end

#pauseObject



170
171
172
# File 'lib/lab/vm.rb', line 170

def pause
  @driver.pause
end

#resetObject



178
179
180
# File 'lib/lab/vm.rb', line 178

def reset
  @driver.reset
end

#resumeObject



182
183
184
# File 'lib/lab/vm.rb', line 182

def resume
  @driver.resume
end

#revert_and_start(snapshot) ⇒ Object



198
199
200
201
# File 'lib/lab/vm.rb', line 198

def revert_and_start(snapshot)
  @driver.revert_snapshot(snapshot)
  @driver.start
end

#revert_snapshot(snapshot) ⇒ Object



190
191
192
# File 'lib/lab/vm.rb', line 190

def revert_snapshot(snapshot)
  @driver.revert_snapshot(snapshot)
end

#run_command(command, timeout = 60) ⇒ Object



211
212
213
# File 'lib/lab/vm.rb', line 211

def run_command(command)
  @driver.run_command(command)
end

#run_script(script, options) ⇒ Object

This isn’t part of the normal API, but too good to pass up.



135
136
137
138
139
140
141
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 135

def run_script(script, options)
	if @session.type == "meterpreter"
		@session.execute_script(script, options)
	else
		raise "Unsupported on #{@session.type}"
	end
end

#running?Boolean

Returns:

  • (Boolean)


154
155
156
# File 'lib/lab/vm.rb', line 154

def running?
  @driver.running?
end

#setup_sessionObject

perform the setup only once



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/lab/modifier/meterpreter_modifier.rb', line 29

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}

     			puts "DEBUG: using options #{options}"

		# 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
			puts "DEBUG: Generated session: #{@session}"
		rescue Exception => e 
		  puts "DEBUG: Unable to exploit"
		  puts e.to_s
		end
	end
	

	
end

#startObject



162
163
164
# File 'lib/lab/vm.rb', line 162

def start
  @driver.start
end

#stopObject



166
167
168
# File 'lib/lab/vm.rb', line 166

def stop
  @driver.stop
end

#suspendObject



174
175
176
# File 'lib/lab/vm.rb', line 174

def suspend
  @driver.suspend
end

#to_sObject



235
236
237
# File 'lib/lab/vm.rb', line 235

def to_s
  return "#{@hostname}"
end

#to_yamlObject



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/lab/vm.rb', line 239

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 += "   description: |\n #{@description}\n"
  out += "   location: #{@location}\n"
  out += "   type: #{@type}\n"
  out += "   tools: #{@tools}\n"
  out += "   os: #{@os}\n"
  out += "   arch: #{@arch}\n"
  
  if @user or @host # Remote vm/drivers only
    out += "   user: #{@user}\n"
    out += "   host: #{@host}\n"
    out += "   port: #{@port}\n"
    out += "   pass: #{@pass}\n"
  end

  if @platform
    out += "   platform: #{@platform}\n"
  end

  if @fog_config
    out += @fog_config.to_yaml
  end

  if @dynagen_config
    out += @dynagen_config.to_yaml
  end

  out += "   credentials:\n"
  @credentials.each do |credential|    
    out += "     - user: #{credential['user']}\n"
    out += "       pass: #{credential['pass']}\n"
  end

   return out
end