class VMIAddressSpace(addrspace.BaseAddressSpace): """ This address space can be used in conjunction with LibVMI and the Python bindings for LibVMI. The end result is that you can connect Volatility to view the memory of a running virtual machine from any virtualization platform that LibVMI supports. For this AS to be instantiated, we need the VM name to connect to. """ order = 90 def __init__(self, base, config, layered=False, **kwargs): self.as_assert(libvmi, "The LibVMI python bindings must be installed") addrspace.BaseAddressSpace.__init__(self, base, config, **kwargs) self.as_assert(base is None or layered, 'Must be first Address Space') self.as_assert(config.LOCATION.startswith("vmi://"), "Location doesn't start with vmi://") domain = config.LOCATION[len("vmi://"):] self.vmi = Libvmi(domain, partial=True) self.dtb = self.vmi.get_vcpu_reg(CR3, 0) def close(self): self.vmi.destroy() def read(self, addr, length): buffer, bytes_read = self.vmi.read_pa(addr, length) if bytes_read != length: raise RuntimeError('Error while reading physical memory at ' '{}'.format(hex(addr))) return buffer def zread(self, addr, length): buffer, bytes_read = self.vmi.read_pa(addr, length) if bytes_read != length: # fill with zeroes buffer += bytes(length - bytes_read).decode() return buffer def write(self, addr, data): bytes_written = self.vmi.write_pa(addr, data) if bytes_written != len(data): return False return True def is_valid_address(self, addr): if addr is None: return False return 4096 < addr < self.vmi.get_memsize() - 1 def get_available_addresses(self): yield (0, self.vmi.get_memsize())
class VMIAddressSpace(addrspace.BaseAddressSpace): """An address space which operates on top of Libvmi's interface.""" __abstract = False __name = "vmi" order = 90 __image = True def __init__(self, base=None, filename=None, session=None, **kwargs): self.as_assert(libvmi, "The LibVMI python bindings must be installed") self.as_assert(base is None, "must be first Address Space") self.session = session url = filename or (session and session.GetParameter("filename")) self.as_assert(url, "Filename must be specified in session (e.g. " "session.SetParameter('filename', 'vmi://domain').") self.as_assert(url.startswith(URL_PREFIX), "The domain must be passed with the URL prefix {}".format(URL_PREFIX)) domain = url[len(URL_PREFIX):] self.as_assert(domain, "domain name missing after {}".format(URL_PREFIX)) super(VMIAddressSpace, self).__init__(base=base, session=session, **kwargs) self.vmi = Libvmi(domain, partial=True) def close(self): self.vmi.destroy() def read(self, addr, size): buffer, bytes_read = self.vmi.read_pa(addr, size) if bytes_read != size: raise RuntimeError('Error while reading physical memory at {}'.format(hex(addr))) return buffer def write(self, addr, data): bytes_written = self.vmi.write_pa(addr, data) if bytes_written != len(data): return False return True def is_valid_address(self, addr): if addr is None: return False return 4096 < addr < self.vmi.get_memsize() - 1 def get_available_addresses(self): yield (4096, self.vmi.get_memsize() - 4096) def get_mappings(self, start=0, end=2 ** 64): yield addrspace.Run(start=0, end=self.vmi.get_memsize(), file_offset=0, address_space=self)
class VMIAddressSpace(addrspace.BaseAddressSpace): """An address space which operates on top of Libvmi's interface.""" __abstract = False __name = "vmi" order = 90 volatile = True __image = True def __init__(self, base=None, filename=None, session=None, **kwargs): self.as_assert(libvmi, "The LibVMI python bindings must be installed") self.as_assert(base is None, "must be first Address Space") self.session = session url = filename or (session and session.GetParameter("filename")) self.as_assert( url, "Filename must be specified in session (e.g. " "session.SetParameter('filename', 'vmi:///domain').") vmi_url = urlparse(url) self.as_assert(vmi_url.scheme == SCHEME, "URL scheme must be vmi://") self.as_assert(vmi_url.path, "No domain name specified") domain = vmi_url.path[1:] # hypervisor specified ? self.mode = None hypervisor = vmi_url.netloc if hypervisor: self.mode = VMIMode[hypervisor.upper()] # query parameters ? self.volatile = True if vmi_url.query: params = parse_qs(vmi_url.query, strict_parsing=True) try: self.volatile = strtobool((params['volatile'][0])) except KeyError: raise RuntimeError('Invalid query parameters in vmi:// URI') # build Libvmi instance super(VMIAddressSpace, self).__init__(base=base, session=session, **kwargs) self.vmi = Libvmi(domain, mode=self.mode, partial=True) self.min_addr = 0 self.max_addr = self.vmi.get_memsize() - 1 # pause in case volatile has been disabled if not self.volatile: self.vmi.pause_vm() # register flush hook to destroy vmi instance when session.Flush() is called session.register_flush_hook(self, self.close) def close(self): if not self.volatile: self.vmi.resume_vm() self.vmi.destroy() def read(self, addr, size): buffer, _ = self.vmi.read_pa(addr, size, padding=True) return buffer def write(self, addr, data): bytes_written = self.vmi.write_pa(addr, data) if bytes_written != len(data): return False return True def is_valid_address(self, addr): if addr is None: return False return self.min_addr <= addr <= self.max_addr def get_available_addresses(self): yield (self.min_addr, self.max_addr) def get_mappings(self, start=0, end=2**64): yield addrspace.Run(start=self.min_addr, end=self.max_addr, file_offset=0, address_space=self)
class VMIAddressSpace(addrspace.BaseAddressSpace): """An address space which operates on top of Libvmi's interface.""" __abstract = False __name = "vmi" order = 90 volatile = True __image = True def __init__(self, base=None, filename=None, session=None, **kwargs): self.as_assert(libvmi, "The LibVMI python bindings must be installed") self.as_assert(base is None, "must be first Address Space") self.session = session url = filename or (session and session.GetParameter("filename")) self.as_assert(url, "Filename must be specified in session (e.g. " "session.SetParameter('filename', 'vmi:///domain').") vmi_url = urlparse(url) self.as_assert(vmi_url.scheme == SCHEME, "URL scheme must be vmi://") self.as_assert(vmi_url.path, "No domain name specified") domain = vmi_url.path[1:] # hypervisor specified ? self.mode = None hypervisor = vmi_url.netloc if hypervisor: self.mode = VMIMode[hypervisor.upper()] # query parameters ? self.volatile = True if vmi_url.query: params = parse_qs(vmi_url.query, strict_parsing=True) try: self.volatile = strtobool((params['volatile'][0])) except KeyError: raise RuntimeError('Invalid query parameters in vmi:// URI') # build Libvmi instance super(VMIAddressSpace, self).__init__(base=base, session=session, **kwargs) self.vmi = Libvmi(domain, mode=self.mode, partial=True) self.min_addr = 0 self.max_addr = self.vmi.get_memsize() - 1 # pause in case volatile has been disabled if not self.volatile: self.vmi.pause_vm() # register flush hook to destroy vmi instance when session.Flush() is called session.register_flush_hook(self, self.close) def close(self): if not self.volatile: self.vmi.resume_vm() self.vmi.destroy() def read(self, addr, size): buffer, _ = self.vmi.read_pa(addr, size, padding=True) return buffer def write(self, addr, data): bytes_written = self.vmi.write_pa(addr, data) if bytes_written != len(data): return False return True def is_valid_address(self, addr): if addr is None: return False return self.min_addr <= addr <= self.max_addr def get_available_addresses(self): yield (self.min_addr, self.max_addr) def get_mappings(self, start=0, end=2 ** 64): yield addrspace.Run(start=self.min_addr, end=self.max_addr, file_offset=0, address_space=self)