def __call__(self, context: interfaces.context.ContextInterface, config_path: str, requirement: interfaces.configuration.RequirementInterface, progress_callback: constants.ProgressCallback = None) -> None: if requirement.unsatisfied(context, config_path): if "pdbscan" not in context.symbol_space: context.symbol_space.append( native.NativeTable("pdbscan", native.std_ctypes)) # TODO: check if this is a windows symbol requirement, otherwise ignore it self._symbol_requirements = self.find_requirements( context, config_path, requirement, requirements.SymbolTableRequirement) potential_layers = self.find_virtual_layers_from_req( context=context, config_path=config_path, requirement=requirement) for sub_config_path, symbol_req in self._symbol_requirements: parent_path = interfaces.configuration.parent_path( sub_config_path) if symbol_req.unsatisfied(context, parent_path): valid_kernel = self.determine_valid_kernel( context, potential_layers, progress_callback) if valid_kernel: self.recurse_symbol_fulfiller(context, valid_kernel, progress_callback) self.set_kernel_virtual_offset(context, valid_kernel) if progress_callback is not None: progress_callback(100, "PDB scanning finished")
def _get_natives(self) -> Optional[interfaces.symbols.NativeTableInterface]: """Determines the appropriate native_types to use from the JSON data.""" native_dict = {} base_types = self._json_object['base_types'] for base_type in base_types: # Void are ignored because voids are not a volatility primitive, they are a specific Volatility object if base_type != 'void': current = base_types[base_type] # TODO: Fix up the typing of this, it bugs out because of the tuple assignment if current['kind'] not in self.format_mapping: raise ValueError("Unsupported base kind") format_val = (current['size'], current['endian'], current['signed']) object_type = self.format_mapping[current['kind']] if base_type == 'pointer': object_type = objects.Pointer native_dict[base_type] = (object_type, format_val) return native.NativeTable(name = "native", native_dictionary = native_dict)
def _read_header(self) -> None: """Checks the vmware header to make sure it's valid.""" if "vmware" not in self._context.symbol_space: self._context.symbol_space.append(native.NativeTable("vmware", native.std_ctypes)) meta_layer = self.context.layers.get(self._meta_layer, None) header_size = struct.calcsize(self.header_structure) data = meta_layer.read(0, header_size) magic, unknown, groupCount = struct.unpack(self.header_structure, data) if magic not in [b"\xD0\xBE\xD2\xBE", b"\xD1\xBA\xD1\xBA", b"\xD2\xBE\xD2\xBE", b"\xD3\xBE\xD3\xBE"]: raise VmwareFormatException(self.name, "Wrong magic bytes for Vmware layer: {}".format(repr(magic))) version = magic[0] & 0xf group_size = struct.calcsize(self.group_structure) groups = {} for group in range(groupCount): name, tag_location, _unknown = struct.unpack( self.group_structure, meta_layer.read(header_size + (group * group_size), group_size)) name = name.rstrip(b"\x00") groups[name] = tag_location memory = groups[b"memory"] tags_read = False offset = memory tags = {} index_len = self._context.symbol_space.get_type("vmware!unsigned int").size while not tags_read: flags = ord(meta_layer.read(offset, 1)) name_len = ord(meta_layer.read(offset + 1, 1)) tags_read = (flags == 0) and (name_len == 0) if not tags_read: name = self._context.object("vmware!string", layer_name = self._meta_layer, offset = offset + 2, max_length = name_len) indices_len = (flags >> 6) & 3 indices = [] for index in range(indices_len): indices.append( self._context.object("vmware!unsigned int", offset = offset + name_len + 2 + (index * index_len), layer_name = self._meta_layer)) data_len = flags & 0x3f if data_len in [62, 63]: # Handle special data sizes that indicate a longer data stream data_len = 4 if version == 0 else 8 # Read the size of the data data_size = self._context.object(self._choose_type(data_len), layer_name = self._meta_layer, offset = offset + 2 + name_len + (indices_len * index_len)) # Skip two bytes of padding (as it seems?) # Read the actual data data = self._context.object("vmware!bytes", layer_name = self._meta_layer, offset = offset + 2 + name_len + (indices_len * index_len) + 2 * data_len + 2, length = data_size) offset += 2 + name_len + (indices_len * index_len) + 2 * data_len + 2 + data_size else: # Handle regular cases data = self._context.object(self._choose_type(data_len), layer_name = self._meta_layer, offset = offset + 2 + name_len + (indices_len * index_len)) offset += 2 + name_len + (indices_len * index_len) + data_len tags[(name, tuple(indices))] = (flags, data) if tags[("regionsCount", ())][1] == 0: raise VmwareFormatException(self.name, "VMware VMEM is not split into regions") for region in range(tags[("regionsCount", ())][1]): offset = tags[("regionPPN", (region, ))][1] * self._page_size mapped_offset = tags[("regionPageNum", (region, ))][1] * self._page_size length = tags[("regionSize", (region, ))][1] * self._page_size self._segments.append((offset, mapped_offset, length, length))