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

Source Code for Module modules.machinery.vmware

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