Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layers - Several fixes around maximum_address and chunk sizes #1141

Merged
merged 12 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions volatility3/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,19 +716,17 @@ def _get_final_filename(self):
"""Gets the final filename"""
if output_dir is None:
raise TypeError("Output directory is not a string")

os.makedirs(output_dir, exist_ok=True)

pref_name_array = self.preferred_filename.split(".")
filename, extension = (
os.path.join(output_dir, ".".join(pref_name_array[:-1])),
pref_name_array[-1],
)
output_filename = f"{filename}.{extension}"
output_filename = os.path.join(output_dir, self.preferred_filename)
filename, extension = os.path.splitext(output_filename)

counter = 1
while os.path.exists(output_filename):
output_filename = f"{filename}-{counter}.{extension}"
output_filename = f"{filename}-{counter}{extension}"
counter += 1

return output_filename

class CLIMemFileHandler(io.BytesIO, CLIFileHandler):
Expand Down Expand Up @@ -792,8 +790,8 @@ def close(self):
return None

self._file.close()
output_filename = self._get_final_filename()
os.rename(self._name, output_filename)
self._output_filename = self._get_final_filename()
ikelos marked this conversation as resolved.
Show resolved Hide resolved
os.rename(self._name, self._output_filename)

if direct:
return CLIDirectFileHandler
Expand Down
2 changes: 1 addition & 1 deletion volatility3/framework/layers/intel.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def _translate_entry(self, offset: int) -> Tuple[int, int]:
position = self._initial_position
entry = self._initial_entry

if self.minimum_address > offset > self.maximum_address:
if not (self.minimum_address <= offset <= self.maximum_address):
raise exceptions.PagedInvalidAddressException(
self.name,
offset,
Expand Down
2 changes: 1 addition & 1 deletion volatility3/framework/layers/segmented.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def maximum_address(self) -> int:
raise ValueError("SegmentedLayer must contain some segments")
if self._maxaddr is None:
mapped, _, length, _ = self._segments[-1]
self._maxaddr = mapped + length
self._maxaddr = mapped + length - 1
return self._maxaddr

@property
Expand Down
19 changes: 12 additions & 7 deletions volatility3/framework/plugins/layerwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class LayerWriter(plugins.PluginInterface):
default_block_size = 0x500000

_required_framework_version = (2, 0, 0)
_version = (2, 0, 0)
_version = (2, 0, 1)

@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
Expand All @@ -38,6 +38,11 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
default=False,
optional=True,
),
requirements.StringRequirement(
ikelos marked this conversation as resolved.
Show resolved Hide resolved
name="output",
description="Output filename",
optional=True,
),
requirements.ListRequirement(
name="layers",
element_type=str,
Expand Down Expand Up @@ -77,7 +82,7 @@ def write_layer(

file_handle = open_method(preferred_name)
for i in range(0, layer.maximum_address, chunk_size):
current_chunk_size = min(chunk_size, layer.maximum_address - i)
current_chunk_size = min(chunk_size, layer.maximum_address + 1 - i)
data = layer.read(i, current_chunk_size, pad=True)
file_handle.write(data)
if progress_callback:
Expand All @@ -95,15 +100,16 @@ def _generator(self):
if not self.config["layers"]:
self.config["layers"] = []
for name in self.context.layers:
if not self.context.layers[name].metadata.get("mapped", False):
if "mapped" not in self.context.layers[name].metadata:
ikelos marked this conversation as resolved.
Show resolved Hide resolved
self.config["layers"] = [name]

for name in self.config["layers"]:
# Check the layer exists and validate the output file
if name not in self.context.layers:
yield 0, (f"Layer Name {name} does not exist",)
else:
output_name = self.config.get("output", ".".join([name, "raw"]))
default_output_name = f"{name}.raw"
ikelos marked this conversation as resolved.
Show resolved Hide resolved
output_name = self.config.get("output", default_output_name)
ikelos marked this conversation as resolved.
Show resolved Hide resolved
try:
file_handle = self.write_layer(
self.context,
Expand All @@ -114,10 +120,9 @@ def _generator(self):
progress_callback=self._progress_callback,
)
file_handle.close()
output_name = file_handle._output_filename
ikelos marked this conversation as resolved.
Show resolved Hide resolved
except IOError as excp:
yield 0, (
f"Layer cannot be written to {self.config['output_name']}: {excp}",
)
yield 0, (f"Layer cannot be written to {output_name}: {excp}",)

yield 0, (f"Layer has been written to {output_name}",)

Expand Down
Loading