コード例 #1
0
    def _mapping(
        self,
        offset: int,
        length: int,
        ignore_errors: bool = False
    ) -> Iterable[Tuple[int, int, int, int, str]]:
        """Returns a sorted iterable of (offset, sublength, mapped_offset, mapped_length, layer)
        mappings.

        This allows translation layers to provide maps of contiguous
        regions in one layer
        """
        if length == 0:
            try:
                mapped_offset, _, layer_name = self._translate(offset)
                if not self._context.layers[layer_name].is_valid(
                        mapped_offset):
                    raise exceptions.InvalidAddressException(
                        layer_name=layer_name, invalid_address=mapped_offset)
            except exceptions.InvalidAddressException:
                if not ignore_errors:
                    raise
                return
            yield offset, length, mapped_offset, length, layer_name
            return
        while length > 0:
            try:
                chunk_offset, page_size, layer_name = self._translate(offset)
                chunk_size = min(page_size - (chunk_offset % page_size),
                                 length)
                if not self._context.layers[layer_name].is_valid(
                        chunk_offset, chunk_size):
                    raise exceptions.InvalidAddressException(
                        layer_name=layer_name, invalid_address=chunk_offset)
            except (exceptions.PagedInvalidAddressException,
                    exceptions.InvalidAddressException) as excp:
                if not ignore_errors:
                    raise
                # We can jump more if we know where the page fault failed
                if isinstance(excp, exceptions.PagedInvalidAddressException):
                    mask = (1 << excp.invalid_bits) - 1
                else:
                    mask = (1 << self._page_size_in_bits) - 1
                length_diff = (mask + 1 - (offset & mask))
                length -= length_diff
                offset += length_diff
            else:
                yield offset, chunk_size, chunk_offset, chunk_size, layer_name
                length -= chunk_size
                offset += chunk_size
コード例 #2
0
ファイル: linear.py プロジェクト: michaelmagyar/volatility3
 def read(self, offset: int, length: int, pad: bool = False) -> bytes:
     """Reads an offset for length bytes and returns 'bytes' (not 'str') of
     length size."""
     current_offset = offset
     output: List[bytes] = []
     for (offset, _, mapped_offset, mapped_length,
          layer) in self.mapping(offset, length, ignore_errors=pad):
         if not pad and offset > current_offset:
             raise exceptions.InvalidAddressException(
                 self.name, current_offset,
                 f"Layer {self.name} cannot map offset: {current_offset}")
         elif offset > current_offset:
             output += [b"\x00" * (offset - current_offset)]
             current_offset = offset
         elif offset < current_offset:
             raise exceptions.LayerException(
                 self.name, "Mapping returned an overlapping element")
         if mapped_length > 0:
             output += [
                 self._context.layers.read(layer, mapped_offset,
                                           mapped_length, pad)
             ]
         current_offset += mapped_length
     recovered_data = b"".join(output)
     return recovered_data + b"\x00" * (length - len(recovered_data))
コード例 #3
0
ファイル: layers.py プロジェクト: ra2003/volatility3
 def read(self, offset: int, length: int, pad: bool = False) -> bytes:
     """Reads an offset for length bytes and returns 'bytes' (not 'str') of
     length size."""
     current_offset = offset
     output = b''  # type: bytes
     for (layer_offset, sublength, mapped_offset, mapped_length,
          layer) in self.mapping(offset, length, ignore_errors=pad):
         if not pad and layer_offset > current_offset:
             raise exceptions.InvalidAddressException(
                 self.name, current_offset,
                 "Layer {} cannot map offset: {}".format(
                     self.name, current_offset))
         elif layer_offset > current_offset:
             output += b"\x00" * (layer_offset - current_offset)
             current_offset = layer_offset
         # The layer_offset can be less than the current_offset in non-linearly mapped layers
         # it does not suggest an overlap, but that the data is in an encoded block
         if mapped_length > 0:
             unprocessed_data = self._context.layers.read(
                 layer, mapped_offset, mapped_length, pad)
             processed_data = self._decode_data(unprocessed_data,
                                                mapped_offset, layer_offset,
                                                sublength)
             if len(processed_data) != sublength:
                 raise ValueError(
                     "ProcessedData length does not match expected length of chunk"
                 )
             output += processed_data
             current_offset += sublength
     return output + (b"\x00" * (length - len(output)))
コード例 #4
0
 def read(self, address: int, length: int, pad: bool = False) -> bytes:
     """Reads the data from the buffer."""
     if not self.is_valid(address, length):
         invalid_address = address
         if self.minimum_address < address <= self.maximum_address:
             invalid_address = self.maximum_address + 1
         raise exceptions.InvalidAddressException(self.name, invalid_address,
                                                  "Offset outside of the buffer boundaries")
     return self._buffer[address:address + length]
コード例 #5
0
    def read(self, offset: int, length: int, pad: bool = False) -> bytes:
        """Reads from the file at offset for length."""
        if not self.is_valid(offset, length):
            invalid_address = offset
            if self.minimum_address < offset <= self.maximum_address:
                invalid_address = self.maximum_address + 1
            raise exceptions.InvalidAddressException(self.name, invalid_address,
                                                     "Offset outside of the buffer boundaries")

        # TODO: implement locking for multi-threading
        with self._lock:
            self._file.seek(offset)
            data = self._file.read(length)

        if len(data) < length:
            if pad:
                data += (b"\x00" * (length - len(data)))
            else:
                raise exceptions.InvalidAddressException(
                    self.name, offset + len(data), "Could not read sufficient bytes from the " + self.name + " file")
        return data
コード例 #6
0
        def read(self, size: int = -1) -> bytes:
            """We ask leechcore to pad the data, because otherwise determining holes in the underlying file would
            be extremely inefficient borderline impossible to do consistently"""
            data = self.handle.read(self._cursor, size, True)

            if len(data) > size:
                data = data[:size]
            else:
                data = data + b'\x00' * (size - len(data))
            self._cursor += len(data)
            if not len(data):
                raise exceptions.InvalidAddressException('LeechCore layer read failure', self._cursor + len(data))
            return data
コード例 #7
0
ファイル: layers.py プロジェクト: michaelmagyar/volatility3
    def write(self, offset: int, value: bytes) -> None:
        """Writes a value at offset, distributing the writing across any
        underlying mapping."""
        current_offset = offset
        length = len(value)
        for (layer_offset, sublength, mapped_offset, mapped_length, layer) in self.mapping(offset, length):
            if layer_offset > current_offset:
                raise exceptions.InvalidAddressException(
                    self.name, current_offset, f"Layer {self.name} cannot map offset: {current_offset}")

            value_chunk = value[layer_offset - offset:layer_offset - offset + sublength]
            new_data = self._encode_data(layer, mapped_offset, layer_offset, value_chunk)
            self._context.layers.write(layer, mapped_offset, new_data)

            current_offset += len(new_data)
コード例 #8
0
ファイル: physical.py プロジェクト: ra2003/volatility3
    def write(self, offset: int, data: bytes) -> None:
        """Writes to the file.

        This will technically allow writes beyond the extent of the file
        """
        if not self.is_valid(offset, len(data)):
            invalid_address = offset
            if self.minimum_address < offset <= self.maximum_address:
                invalid_address = self.maximum_address + 1
            raise exceptions.InvalidAddressException(
                self.name, invalid_address, "Data segment outside of the " +
                self.name + " file boundaries")
        with self._lock:
            self._file.seek(offset)
            self._file.write(data)
コード例 #9
0
ファイル: linear.py プロジェクト: michaelmagyar/volatility3
 def write(self, offset: int, value: bytes) -> None:
     """Writes a value at offset, distributing the writing across any
     underlying mapping."""
     current_offset = offset
     length = len(value)
     for (offset, _, mapped_offset, length,
          layer) in self.mapping(offset, length):
         if offset > current_offset:
             raise exceptions.InvalidAddressException(
                 self.name, current_offset,
                 f"Layer {self.name} cannot map offset: {current_offset}")
         elif offset < current_offset:
             raise exceptions.LayerException(
                 self.name, "Mapping returned an overlapping element")
         self._context.layers.write(layer, mapped_offset, value[:length])
         value = value[length:]
         current_offset += length
コード例 #10
0
    def _find_segment(self, offset: int, next: bool = False) -> Tuple[int, int, int, int]:
        """Finds the segment containing a given offset.

        Returns the segment tuple (offset, mapped_offset, length, mapped_length)
        """

        if not self._segments:
            self._load_segments()

        # Find rightmost value less than or equal to x
        i = bisect_right(self._segments, (offset, self.context.layers[self._base_layer].maximum_address))
        if i and not next:
            segment = self._segments[i - 1]
            if segment[0] <= offset < segment[0] + segment[2]:
                return segment
        if next:
            if i < len(self._segments):
                return self._segments[i]
        raise exceptions.InvalidAddressException(self.name, offset, "Invalid address at {:0x}".format(offset))
コード例 #11
0
 def mapping(self,
             offset: int,
             length: int,
             ignore_errors: bool = False) -> Iterable[Tuple[int, int, int, int, str]]:
     returned = 0
     page_size = self._pdb_layer.page_size
     while length > 0:
         page = math.floor((offset + returned) / page_size)
         page_position = ((offset + returned) % page_size)
         chunk_size = min(page_size - page_position, length)
         if page >= self._pages_len:
             if not ignore_errors:
                 raise exceptions.InvalidAddressException(layer_name = self.name,
                                                          invalid_address = offset + returned)
         else:
             yield offset + returned, chunk_size, (self._pages[page] *
                                                   page_size) + page_position, chunk_size, self._base_layer
         returned += chunk_size
         length -= chunk_size
コード例 #12
0
    def write(self, offset: int, data: bytes) -> None:
        """Writes to the file.

        This will technically allow writes beyond the extent of the file
        """
        if not self._file.writable():
            if not self._write_warning:
                self._write_warning = True
                vollog.warning(f"Try to write to unwritable layer: {self.name}")
            return None
        if not self.is_valid(offset, len(data)):
            invalid_address = offset
            if self.minimum_address < offset <= self.maximum_address:
                invalid_address = self.maximum_address + 1
            raise exceptions.InvalidAddressException(self.name, invalid_address,
                                                     "Data segment outside of the " + self.name + " file boundaries")
        with self._lock:
            self._file.seek(offset)
            self._file.write(data)
コード例 #13
0
ファイル: linear.py プロジェクト: michaelmagyar/volatility3
 def translate(
         self,
         offset: int,
         ignore_errors: bool = False
 ) -> Tuple[Optional[int], Optional[str]]:
     mapping = list(self.mapping(offset, 0, ignore_errors))
     if len(mapping) == 1:
         original_offset, _, mapped_offset, _, layer = mapping[0]
         if original_offset != offset:
             raise exceptions.LayerException(
                 self.name,
                 f"Layer {self.name} claims to map linearly but does not")
     else:
         if ignore_errors:
             # We should only hit this if we ignored errors, but check anyway
             return None, None
         raise exceptions.InvalidAddressException(
             self.name, offset,
             f"Cannot translate {offset} in layer {self.name}")
     return mapped_offset, layer
コード例 #14
0
ファイル: __init__.py プロジェクト: michaelmagyar/volatility3
    def get_peb(self) -> interfaces.objects.ObjectInterface:
        """Constructs a PEB object"""
        if constants.BANG not in self.vol.type_name:
            raise ValueError(
                f"Invalid symbol table name syntax (no {constants.BANG} found)"
            )

        # add_process_layer can raise InvalidAddressException.
        # if that happens, we let the exception propagate upwards
        proc_layer_name = self.add_process_layer()

        proc_layer = self._context.layers[proc_layer_name]
        if not proc_layer.is_valid(self.Peb):
            raise exceptions.InvalidAddressException(
                proc_layer_name, self.Peb, f"Invalid address at {self.Peb:0x}")

        sym_table = self.vol.type_name.split(constants.BANG)[0]
        peb = self._context.object(f"{sym_table}{constants.BANG}_PEB",
                                   layer_name=proc_layer_name,
                                   offset=self.Peb)
        return peb