Package modules :: Package machinery :: Module vmware
[hide private]
[frames] | no frames]

Source Code for Module modules.machinery.vmware

  1  # Copyright (C) 2010-2015 Cuckoo Foundation. 
  2  # This file was originally produced by Mike Tu. 
  3  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  4  # See the file 'docs/LICENSE' for copying permission. 
  5   
  6  import glob 
  7  import logging 
  8  import subprocess 
  9  import os.path 
 10  import shutil 
 11  import time 
 12   
 13  from lib.cuckoo.common.abstracts import Machinery 
 14  from lib.cuckoo.common.exceptions import CuckooMachineError 
 15   
 16  log = logging.getLogger(__name__) 
 17   
18 -class VMware(Machinery):
19 """Virtualization layer for VMware Workstation using vmrun utility.""" 20 LABEL = "vmx_path" 21
22 - def _initialize_check(self):
23 """Check for configuration file and vmware setup. 24 @raise CuckooMachineError: if configuration is missing or wrong. 25 """ 26 if not self.options.vmware.path: 27 raise CuckooMachineError("VMware vmrun path missing, " 28 "please add it to vmware.conf") 29 30 if not os.path.exists(self.options.vmware.path): 31 raise CuckooMachineError("VMware vmrun not found in " 32 "specified path %s" % 33 self.options.vmware.path) 34 # Consistency checks. 35 for machine in self.machines(): 36 vmx_path = machine.label 37 38 snapshot = self._snapshot_from_vmx(vmx_path) 39 self._check_vmx(vmx_path) 40 self._check_snapshot(vmx_path, snapshot) 41 42 # Base checks. 43 super(VMware, self)._initialize_check()
44
45 - def _check_vmx(self, vmx_path):
46 """Checks whether a vmx file exists and is valid. 47 @param vmx_path: path to vmx file 48 @raise CuckooMachineError: if file not found or not ending with .vmx 49 """ 50 if not vmx_path.endswith(".vmx"): 51 raise CuckooMachineError("Wrong configuration: vm path not " 52 "ending with .vmx: %s)" % vmx_path) 53 54 if not os.path.exists(vmx_path): 55 raise CuckooMachineError("Vm file %s not found" % vmx_path)
56
57 - def _check_snapshot(self, vmx_path, snapshot):
58 """Checks snapshot existance. 59 @param vmx_path: path to vmx file 60 @param snapshot: snapshot name 61 @raise CuckooMachineError: if snapshot not found 62 """ 63 try: 64 p = subprocess.Popen([self.options.vmware.path, 65 "listSnapshots", vmx_path], 66 stdout=subprocess.PIPE, 67 stderr=subprocess.PIPE) 68 output, _ = p.communicate() 69 except OSError as e: 70 raise CuckooMachineError("Unable to get snapshot list for %s. " 71 "Reason: %s" % (vmx_path, e)) 72 else: 73 if output: 74 return snapshot in output 75 else: 76 raise CuckooMachineError("Unable to get snapshot list for %s. " 77 "No output from " 78 "`vmrun listSnapshots`" % vmx_path)
79
80 - def start(self, vmx_path):
81 """Start a virtual machine. 82 @param vmx_path: path to vmx file. 83 @raise CuckooMachineError: if unable to start. 84 """ 85 snapshot = self._snapshot_from_vmx(vmx_path) 86 87 # Preventive check 88 if self._is_running(vmx_path): 89 raise CuckooMachineError("Machine %s is already running" % 90 vmx_path) 91 92 self._revert(vmx_path, snapshot) 93 94 time.sleep(3) 95 96 log.debug("Starting vm %s" % vmx_path) 97 try: 98 p = subprocess.Popen([self.options.vmware.path, 99 "start", vmx_path, 100 self.options.vmware.mode], 101 stdout=subprocess.PIPE, 102 stderr=subprocess.PIPE) 103 if self.options.vmware.mode.lower() == "gui": 104 output, _ = p.communicate() 105 if output: 106 raise CuckooMachineError("Unable to start machine " 107 "%s: %s" % (vmx_path, output)) 108 except OSError as e: 109 mode = self.options.vmware.mode.upper() 110 raise CuckooMachineError("Unable to start machine %s in %s " 111 "mode: %s" % (vmx_path, mode, e))
112
113 - def stop(self, vmx_path):
114 """Stops a virtual machine. 115 @param vmx_path: path to vmx file 116 @raise CuckooMachineError: if unable to stop. 117 """ 118 log.debug("Stopping vm %s" % vmx_path) 119 if self._is_running(vmx_path): 120 try: 121 if subprocess.call([self.options.vmware.path, 122 "stop", vmx_path, "hard"], 123 stdout=subprocess.PIPE, 124 stderr=subprocess.PIPE): 125 raise CuckooMachineError("Error shutting down " 126 "machine %s" % vmx_path) 127 except OSError as e: 128 raise CuckooMachineError("Error shutting down machine " 129 "%s: %s" % (vmx_path, e)) 130 else: 131 log.warning("Trying to stop an already stopped machine: %s", 132 vmx_path)
133
134 - def _revert(self, vmx_path, snapshot):
135 """Revets machine to snapshot. 136 @param vmx_path: path to vmx file 137 @param snapshot: snapshot name 138 @raise CuckooMachineError: if unable to revert 139 """ 140 log.debug("Revert snapshot for vm %s" % vmx_path) 141 try: 142 if subprocess.call([self.options.vmware.path, 143 "revertToSnapshot", vmx_path, snapshot], 144 stdout=subprocess.PIPE, 145 stderr=subprocess.PIPE): 146 raise CuckooMachineError("Unable to revert snapshot for " 147 "machine %s: vmrun exited with " 148 "error" % vmx_path) 149 except OSError as e: 150 raise CuckooMachineError("Unable to revert snapshot for " 151 "machine %s: %s" % (vmx_path, e))
152
153 - def _is_running(self, vmx_path):
154 """Checks if virtual machine is running. 155 @param vmx_path: path to vmx file 156 @return: running status 157 """ 158 try: 159 p = subprocess.Popen([self.options.vmware.path, "list"], 160 stdout=subprocess.PIPE, 161 stderr=subprocess.PIPE) 162 output, error = p.communicate() 163 except OSError as e: 164 raise CuckooMachineError("Unable to check running status for %s. " 165 "Reason: %s" % (vmx_path, e)) 166 else: 167 if output: 168 return vmx_path in output 169 else: 170 raise CuckooMachineError("Unable to check running status " 171 "for %s. No output from " 172 "`vmrun list`" % vmx_path)
173
174 - def _snapshot_from_vmx(self, vmx_path):
175 """Get snapshot for a given vmx file. 176 @param vmx_path: configuration option from config file 177 """ 178 vm_info = self.db.view_machine_by_label(vmx_path) 179 return vm_info.snapshot
180
181 - def dump_memory(self, vmx_path, path):
182 """Take a memory dump of the machine.""" 183 if not os.path.exists(vmx_path): 184 raise CuckooMachineError("Can't find .vmx file {0}. Ensure to configure a fully qualified path in vmware.conf (key = vmx_path)".format(vmx_path)) 185 186 try: 187 subprocess.call([self.options.vmware.path, "snapshot", 188 vmx_path, "memdump"], 189 stdout=subprocess.PIPE, 190 stderr=subprocess.PIPE) 191 except OSError as e: 192 raise CuckooMachineError("vmrun failed to take a memory dump of the machine with label %s: %s" % (vmx_path, e)) 193 194 vmwarepath, _ = os.path.split(vmx_path) 195 latestvmem = max(glob.iglob(os.path.join(vmwarepath, "*.vmem")), 196 key=os.path.getctime) 197 198 # We need to move the snapshot to the current analysis directory as 199 # vmware doesn't support an option for the destination path :-/ 200 shutil.move(latestvmem, path) 201 202 # Old snapshot can be deleted, as it isn't needed any longer. 203 try: 204 subprocess.call([self.options.vmware.path, "deleteSnapshot", 205 vmx_path, "memdump"], 206 stdout=subprocess.PIPE, 207 stderr=subprocess.PIPE) 208 except OSError as e: 209 raise CuckooMachineError("vmrun failed to delete the temporary snapshot in %s: %s" % (vmx_path, e)) 210 211 log.info("Successfully generated memory dump for virtual machine with label %s ", vmx_path)
212