def __init__(self, base, config, layered=False, **kwargs): addrspace.BaseAddressSpace.__init__(self, base, config, **kwargs) self.as_assert(base == None or layered, 'Must be first address space') if config.LOPHI_CACHE: logger.info("LO-PHI Cache ENABLED.") cache_timeout = 1 else: cache_timeout = 0 if config.LOCATION.startswith("lophi://"): location = config.LOCATION[8:] self.client = MemorySensorPhysical(location, cache_timeout=cache_timeout) elif config.LOCATION.startswith("vmi://"): location = config.LOCATION[6:] self.client = MemorySensorVirtual(location, cache_timeout=cache_timeout) self.dtb = self.get_cr3() else: raise ( "Not a valid LO-PHI URN. (lophi:// for physical and vmi:// for virtual)" ) self.fname = location self.name = location self.cache = False self.cache_data = {} self.address = 0 if config.RAM_SIZE is None: print "ERROR/LO-PHI: No RAM size defined. (e.g. --ram_size=12GB)" sys.exit(0) self.size = self.parse_byte_amount(config.RAM_SIZE) self.config = config self._exclusions = sorted( []) # no info about the HW, nothing to exclude
def __init__(self, base, config, layered=False, **kwargs): addrspace.BaseAddressSpace.__init__(self, base, config, **kwargs) self.as_assert(base == None or layered, 'Must be first address space') if config.LOPHI_CACHE: logger.info("LO-PHI Cache ENABLED.") cache_timeout = 1 else: cache_timeout = 0 if config.LOCATION.startswith("lophi://"): location = config.LOCATION[8:] self.client = MemorySensorPhysical(location, cache_timeout=cache_timeout) elif config.LOCATION.startswith("vmi://"): location = config.LOCATION[6:] self.client = MemorySensorVirtual(location, cache_timeout=cache_timeout) self.dtb = self.get_cr3() else: raise("Not a valid LO-PHI URN. (lophi:// for physical and vmi:// for virtual)") self.fname = location self.name = location self.cache = False self.cache_data = {} self.address = 0 if config.RAM_SIZE is None: print "ERROR/LO-PHI: No RAM size defined. (e.g. --ram_size=12GB)" sys.exit(0) self.size = self.parse_byte_amount(config.RAM_SIZE) self.config = config self._exclusions = sorted([]) # no info about the HW, nothing to exclude
def main(options): if options.replay_file is not None: cap_reader = CaptureReader(options.replay_file) for (ts, data) in cap_reader: print "Time: ", ts, "s" print MemorySensorPacket(data) return if options.sensor_type == G.MACHINE_TYPES.PHYSICAL: client = MemorySensorPhysical(options.target, cache_timeout=0, use_threading=False) else: client = MemorySensorVirtual(options.target) READ_SIZE = int(options.read_size) start_addr = options.startaddr # Create our output file try: os.makedirs(os.path.dirname(options.output)) except: pass try: mcap_writer = None if options.loop_forever == True: logger.debug("Creating capture file.") options.output += ".mcap" mcap_writer = CaptureWriter(options.output) mcap_writer.start() else: logger.debug("Creating dump file.") options.output += ".mfd" output_file = open(options.output, "w+") except: print "ERROR: Could not open output file." sys.exit(0) # Read memory count = 0 start = time.time() sensor_packet = MemorySensorPacket() while True: try: # Get memory from remote system # Read memory data = client.read(start_addr, READ_SIZE) # Write to file? if not options.loop_forever: output_file.write(data) else: sensor_packet.address = start_addr sensor_packet.data = data sensor_packet.length = READ_SIZE mcap_writer.put(sensor_packet) # Just read once? if not options.loop_forever: break else: print "Completed read #%d" % count count += 1 except: # Just finish up break end = time.time() # Do we have an mcap file to close? if mcap_writer is not None: mcap_writer.stop() else: # Close output file output_file.close() print "Memory dump (%d bytes) written to %s. Took %s seconds." % ( len(data), options.output, end - start)
class LoPhiAddressSpace(addrspace.BaseAddressSpace): """Address space for using LO-PHI memory sensor. Mediates requests for the contents of a physical address and length through the network to a LO-PHI memory device. This is selected for locations of type 'lophi://hostname-or-IPv4'""" order = 98 def __init__(self, base, config, layered=False, **kwargs): addrspace.BaseAddressSpace.__init__(self, base, config, **kwargs) self.as_assert(base == None or layered, 'Must be first address space') if config.LOPHI_CACHE: logger.info("LO-PHI Cache ENABLED.") cache_timeout = 1 else: cache_timeout = 0 if config.LOCATION.startswith("lophi://"): location = config.LOCATION[8:] self.client = MemorySensorPhysical(location, cache_timeout=cache_timeout) elif config.LOCATION.startswith("vmi://"): location = config.LOCATION[6:] self.client = MemorySensorVirtual(location, cache_timeout=cache_timeout) self.dtb = self.get_cr3() else: raise ( "Not a valid LO-PHI URN. (lophi:// for physical and vmi:// for virtual)" ) self.fname = location self.name = location self.cache = False self.cache_data = {} self.address = 0 if config.RAM_SIZE is None: print "ERROR/LO-PHI: No RAM size defined. (e.g. --ram_size=12GB)" sys.exit(0) self.size = self.parse_byte_amount(config.RAM_SIZE) self.config = config self._exclusions = sorted( []) # no info about the HW, nothing to exclude def set_cache(self, status): """ Enable/Disable caching """ self.cache = status if status == False: self.cache_data = {} def read(self, addr, length): """ Read data from memory @param addr: Address to read from @param lengt: Length of data to read """ return self.client.read(addr, length) def write(self, addr, data): """ Write data to memory @param addr: Address to write to @param data: Data to write to memory """ nbytes = self.vmi.write_pa(addr, data) if nbytes != len(data): return False return True def get_cr3(self): """ Return cr3 value with virtual sensor only """ if isinstance(self.client, MemorySensorVirtual): return self.client.get_vcpureg("cr3", 0) else: return None """ Unsure what all of these do, but Josh implement them. Leaving them to investigate later. """ @staticmethod def register_options(config): config.add_option( "RETRIES", type='int', default=5, help="Maximum attempts to retry a timed-out LO-PHI request") config.add_option("TIMEOUT", type='float', default=0.5, help="Timeout period for LO-PHI read operations") config.add_option( "RAM_SIZE", type='string', help= "Amount of RAM in the target device. This is used to bound scans." " Units can be bytes, or KB with 'K' or 'KB' suffix, MB with 'M' or 'MB' " "suffix, or GB with 'G' or 'GB' suffix.") config.add_option("LOPHI_CACHE", type='int', default=False, help="Enable caching for LO-PHI.") # There are no kibibytes, mebibytes, or gibibytes in this program. @staticmethod def parse_byte_amount(spec_string): if spec_string is None: return None spec_string = str(spec_string) normalized = spec_string.lower().strip() multiplier = 1 if normalized.endswith('kb') or normalized.endswith('k'): multiplier = 1024 elif normalized.endswith('mb') or normalized.endswith('m'): multiplier = 1024 * 1024 elif normalized.endswith('gb') or normalized.endswith('g'): multiplier = 1024 * 1024 * 1024 if normalized[-1] == 'b': normalized = normalized[:-2] elif not normalized[-1].isdigit(): #while not normalized[-1].isdigit(): normalized = normalized[:-1] return int(normalized) * multiplier def intervals(self, start, end): return [(start, end)] def fread(self, len): data = self.read(self.address, len) self.address += len return data def zread(self, addr, len): return self.read(addr, len) def read_long(self, addr): string = self.read(addr, 4) (longval, ) = struct.unpack('=L', string) return longval def get_available_addresses(self): yield (0, self.size - 1) def is_valid_address(self, addr): if addr == None: return False return self.size is None or addr < self.size def close(self): #self.fhandle.close() pass def subscribe(self, startaddr, endaddr, data, threadclass): return self.client.subscribe_api(startaddr, endaddr, data, threadclass)
class LoPhiAddressSpace(addrspace.BaseAddressSpace): """Address space for using LO-PHI memory sensor. Mediates requests for the contents of a physical address and length through the network to a LO-PHI memory device. This is selected for locations of type 'lophi://hostname-or-IPv4'""" order = 98 def __init__(self, base, config, layered=False, **kwargs): addrspace.BaseAddressSpace.__init__(self, base, config, **kwargs) self.as_assert(base == None or layered, 'Must be first address space') if config.LOPHI_CACHE: logger.info("LO-PHI Cache ENABLED.") cache_timeout = 1 else: cache_timeout = 0 if config.LOCATION.startswith("lophi://"): location = config.LOCATION[8:] self.client = MemorySensorPhysical(location, cache_timeout=cache_timeout) elif config.LOCATION.startswith("vmi://"): location = config.LOCATION[6:] self.client = MemorySensorVirtual(location, cache_timeout=cache_timeout) self.dtb = self.get_cr3() else: raise("Not a valid LO-PHI URN. (lophi:// for physical and vmi:// for virtual)") self.fname = location self.name = location self.cache = False self.cache_data = {} self.address = 0 if config.RAM_SIZE is None: print "ERROR/LO-PHI: No RAM size defined. (e.g. --ram_size=12GB)" sys.exit(0) self.size = self.parse_byte_amount(config.RAM_SIZE) self.config = config self._exclusions = sorted([]) # no info about the HW, nothing to exclude def set_cache(self,status): """ Enable/Disable caching """ self.cache = status if status == False: self.cache_data = {} def read(self, addr, length): """ Read data from memory @param addr: Address to read from @param lengt: Length of data to read """ return self.client.read(addr,length) def write(self, addr, data): """ Write data to memory @param addr: Address to write to @param data: Data to write to memory """ nbytes = self.vmi.write_pa(addr, data) if nbytes != len(data): return False return True def get_cr3(self): """ Return cr3 value with virtual sensor only """ if isinstance(self.client,MemorySensorVirtual): return self.client.get_vcpureg("cr3", 0); else: return None """ Unsure what all of these do, but Josh implement them. Leaving them to investigate later. """ @staticmethod def register_options(config): config.add_option("RETRIES", type = 'int', default = 5, help = "Maximum attempts to retry a timed-out LO-PHI request") config.add_option("TIMEOUT", type = 'float', default = 0.5, help = "Timeout period for LO-PHI read operations") config.add_option("RAM_SIZE", type = 'string', help = "Amount of RAM in the target device. This is used to bound scans." " Units can be bytes, or KB with 'K' or 'KB' suffix, MB with 'M' or 'MB' " "suffix, or GB with 'G' or 'GB' suffix.") config.add_option("LOPHI_CACHE", type = 'int', default = False, help="Enable caching for LO-PHI.") # There are no kibibytes, mebibytes, or gibibytes in this program. @staticmethod def parse_byte_amount(spec_string): if spec_string is None: return None spec_string = str(spec_string) normalized = spec_string.lower().strip() multiplier = 1 if normalized.endswith ('kb') or normalized.endswith('k'): multiplier = 1024 elif normalized.endswith('mb') or normalized.endswith('m'): multiplier = 1024*1024 elif normalized.endswith('gb') or normalized.endswith('g'): multiplier = 1024*1024*1024 if normalized[-1] == 'b': normalized = normalized[:-2] elif not normalized[-1].isdigit(): #while not normalized[-1].isdigit(): normalized = normalized[:-1] return int(normalized) * multiplier def intervals(self, start, end): return [(start,end)] def fread(self,len): data = self.read(self.address,len) self.address += len return data def zread(self, addr, len): return self.read(addr, len) def read_long(self, addr): string = self.read(addr, 4) (longval, ) = struct.unpack('=L', string) return longval def get_available_addresses(self): yield (0,self.size -1) def is_valid_address(self, addr): if addr == None: return False return self.size is None or addr < self.size def close(self): #self.fhandle.close() pass def subscribe(self, startaddr, endaddr, data, threadclass): return self.client.subscribe_api(startaddr, endaddr, data, threadclass)
def __init__(self, vm_name, vm_type=G.MACHINE_TYPES.KVM, static_mac=None, memory_size=1073741824, cpu_count=1, force_new=False, volatility_profile=None, **kargs): """ Initialize @param config: Machine configuration object @param init_sensors: Initialize all sensors by default """ # Initialize our state variables self.type = vm_type self.MACHINE_TYPE = vm_type class MachineConfig(): # Name name = vm_name # DISK disk = os.path.join(G.DIR_ROOT,G.DIR_VM_OUTPUT,vm_name+".qcow2") disk_base = None # Config vm_config = os.path.join(G.DIR_ROOT,G.DIR_VM_OUTPUT,vm_name+".xml") config = MachineConfig() # MAC if static_mac is None: config.__dict__['mac_addr'] = self.__get_new_mac() else: config.__dict__['mac_addr'] = static_mac config.__dict__['vm_name'] = vm_name config.__dict__['memory_size'] = memory_size config.__dict__['cpu_count'] = cpu_count config.__dict__['volatility_profile'] = volatility_profile Machine.__init__(self, config) # Add all of our sensors # Control sensor must be added first to interact with libvirt self.add_sensor(ControlSensorVirtual(vm_name,vm_type)) # What state are we in? state = self.control.get_state() # UKNOWN is does not exist if force_new and state is None: self.lophi_init() elif state != G.SENSOR_CONTROL.POWER_STATUS.UNKNOWN: logger.debug("VM (%s) already exists."%self.config.name) # Add all of our sensors to this VM vm_disk = self.disk_get_filename() if vm_disk is not None: self.add_sensor(DiskSensorVirtual(vm_disk)) else: self.add_sensor(DiskSensorVirtual(self.config.disk)) self.add_sensor(CPUSensorVirtual(config.vm_name)) self.add_sensor(MemorySensorVirtual(config.vm_name)) net_iface = self.network_get_interface() if net_iface is not None: self.add_sensor(NetworkSensorVirtual(net_iface)) else: logger.warn("No network intface exists for %s"%self.config.vm_name) # Do we need to mutex these accesses? self.REQUIRE_MUTEX = False if "require_mutex" in kargs and kargs['require_mutex']: self.REQUIRE_MUTEX = True # Force a completely fresh instance? if "force_new" in kargs and kargs['force_new']: # Poweroff existing machine self.control.power_off()