Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 0 additions & 2 deletions development/banner_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@


class BannerCacheGenerator:

def __init__(self, path: str, url_prefix: str):
self._path = path
self._url_prefix = url_prefix
Expand Down Expand Up @@ -79,7 +78,6 @@ def run(self):


if __name__ == "__main__":

parser = argparse.ArgumentParser()
parser.add_argument("--path", default=os.path.dirname(__file__))
parser.add_argument(
Expand Down
1 change: 0 additions & 1 deletion development/compare-vol.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ def plugin_cmd(self, plugin: VolatilityPlugin, image: VolatilityImage) -> List[s


class VolatilityTester:

def __init__(
self,
images: List[VolatilityImage],
Expand Down
1 change: 0 additions & 1 deletion development/pdbparse-to-json.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@


class PDBRetreiver:

def retreive_pdb(self, guid: str, file_name: str) -> Optional[str]:
logger.info("Download PDB file...")
file_name = ".".join(file_name.split(".")[:-1] + ["pdb"])
Expand Down
1 change: 0 additions & 1 deletion development/stock-linux-json.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@


class Downloader:

def __init__(self, url_lists: List[List[str]]) -> None:
self.url_lists = url_lists

Expand Down
2,036 changes: 1,809 additions & 227 deletions test/plugins/windows/test_scheduled_tasks.py

Large diffs are not rendered by default.

64 changes: 53 additions & 11 deletions test/renderers/test_parquet_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
import pyarrow as pa
import pyarrow.parquet as pq
import pyarrow.compute as pc

HAS_PYARROW = True
except ImportError:
# The user doesn't have pyarrow installed, but HAS_PYARROW will be false so just continue
# The user doesn't have pyarrow installed, but HAS_PYARROW will be false so just continue
pass


Expand Down Expand Up @@ -41,10 +42,33 @@ def test_windows_generic_pslist(self, volatility, python, image):
table = self._get_table_from_output(out)
assert table.num_rows > 10

assert table.filter(pc.match_substring(pc.utf8_lower(table.column('ImageFileName')), "system")).num_rows > 0
assert table.filter(pc.match_substring(pc.utf8_lower(table.column('ImageFileName')), "csrss.exe")).num_rows > 0
assert table.filter(pc.match_substring(pc.utf8_lower(table.column('ImageFileName')), "svchost.exe")).num_rows > 0
assert table.filter(pc.greater(table.column('PID'), 0)).num_rows == table.num_rows
assert (
table.filter(
pc.match_substring(
pc.utf8_lower(table.column("ImageFileName")), "system"
)
).num_rows
> 0
)
assert (
table.filter(
pc.match_substring(
pc.utf8_lower(table.column("ImageFileName")), "csrss.exe"
)
).num_rows
> 0
)
assert (
table.filter(
pc.match_substring(
pc.utf8_lower(table.column("ImageFileName")), "svchost.exe"
)
).num_rows
> 0
)
assert (
table.filter(pc.greater(table.column("PID"), 0)).num_rows == table.num_rows
)

def test_linux_generic_pslist(self, volatility, python, image):
rc, out, _err = test_volatility.runvol_plugin(
Expand All @@ -59,12 +83,23 @@ def test_linux_generic_pslist(self, volatility, python, image):
table = self._get_table_from_output(out)
assert table.num_rows > 10

init_rows = table.filter(pc.match_substring(pc.utf8_lower(table.column('COMM')), "init"))
systemd_rows = table.filter(pc.match_substring(pc.utf8_lower(table.column('COMM')), "systemd"))
init_rows = table.filter(
pc.match_substring(pc.utf8_lower(table.column("COMM")), "init")
)
systemd_rows = table.filter(
pc.match_substring(pc.utf8_lower(table.column("COMM")), "systemd")
)
assert (init_rows.num_rows > 0) or (systemd_rows.num_rows > 0)

assert table.filter(pc.match_substring(pc.utf8_lower(table.column('COMM')), "watchdog")).num_rows > 0
assert table.filter(pc.greater(table.column('PID'), 0)).num_rows == table.num_rows
assert (
table.filter(
pc.match_substring(pc.utf8_lower(table.column("COMM")), "watchdog")
).num_rows
> 0
)
assert (
table.filter(pc.greater(table.column("PID"), 0)).num_rows == table.num_rows
)

def test_windows_generic_handles(self, volatility, python, image):
rc, out, _err = test_volatility.runvol_plugin(
Expand All @@ -79,7 +114,14 @@ def test_windows_generic_handles(self, volatility, python, image):

table = self._get_table_from_output(out)
assert table.num_rows > 500
assert table.filter(pc.match_substring(pc.utf8_lower(table.column('Name')), "machine\\system")).num_rows > 0
assert (
table.filter(
pc.match_substring(
pc.utf8_lower(table.column("Name")), "machine\\system"
)
).num_rows
> 0
)

def test_linux_generic_lsof(self, volatility, python, image):
rc, out, _err = test_volatility.runvol_plugin(
Expand All @@ -94,6 +136,7 @@ def test_linux_generic_lsof(self, volatility, python, image):
table = self._get_table_from_output(out)
assert table.num_rows > 35


class TestParquetRenderer(TestArrowRendererBase):
renderer_format = "parquet"

Expand All @@ -106,4 +149,3 @@ class TestArrowRenderer(TestArrowRendererBase):

def _get_table_from_output(self, output_bytes):
return pa.ipc.open_stream(io.BytesIO(output_bytes)).read_all()

10 changes: 5 additions & 5 deletions test/volatility3_code_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def __str__(self):


class UnrequiredVersionableUsage(CodeViolation):

def __init__(
self,
module: types.ModuleType,
Expand All @@ -107,7 +106,6 @@ def __str__(self) -> str:


class DirectVolatilityImportUsage(CodeViolation):

def __init__(
self,
module: types.ModuleType,
Expand Down Expand Up @@ -174,8 +172,11 @@ def _check_vol3_import_from(self, node: ast.ImportFrom):
"""
if (
node.module
and node.module.startswith("volatility3.") # Give a pass to volatility3 module
and node.module != "volatility3.framework.constants._version" # make an exception for this
and node.module.startswith(
"volatility3."
) # Give a pass to volatility3 module
and node.module
!= "volatility3.framework.constants._version" # make an exception for this
):
for name in node.names:
try:
Expand Down Expand Up @@ -204,7 +205,6 @@ def _check_vol3_import_from(self, node: ast.ImportFrom):
def enter_ImportFrom(self, node: ast.ImportFrom):
self._check_vol3_import_from(node)


def enter_ClassDef(self, node: ast.ClassDef) -> Any:
logger.debug("Entering class %s", node.name)
clazz = None
Expand Down
1 change: 1 addition & 0 deletions volatility3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
"""Volatility 3 - An open-source memory forensics framework"""

import inspect
import sys
from importlib import abc
Expand Down
10 changes: 6 additions & 4 deletions volatility3/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* run the plugin
* display the results
"""

import argparse
import inspect
import io
Expand Down Expand Up @@ -458,8 +459,9 @@ def run(self):
raise ValueError(
"Invalid extension (extensions must be of the format \"conf.path.value='value'\")"
)
address, value = extension[: extension.find("=")], json.loads(
extension[extension.find("=") + 1 :]
address, value = (
extension[: extension.find("=")],
json.loads(extension[extension.find("=") + 1 :]),
)
ctx.config[address] = value

Expand Down Expand Up @@ -574,7 +576,7 @@ def load_system_defaults(
delayed_logs.append(
(
logging.DEBUG,
f"Loaded configuration: {json.dumps(result, indent = 2, sort_keys = True)}",
f"Loaded configuration: {json.dumps(result, indent=2, sort_keys=True)}",
)
)
return delayed_logs, result
Expand Down Expand Up @@ -763,7 +765,7 @@ def order_extra_verbose_levels(self):
constants.LOGLEVEL_VVVV,
]
):
logging.addLevelName(level_value, f"DETAIL {level+1}")
logging.addLevelName(level_value, f"DETAIL {level + 1}")

def file_handler_class_factory(self, direct=True):
output_dir = self.output_dir
Expand Down
2 changes: 0 additions & 2 deletions volatility3/cli/text_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ def ignored_columns(


class QuickTextRenderer(CLIRenderer):

name = "quick"

def get_render_options(self):
Expand Down Expand Up @@ -348,7 +347,6 @@ def render(self, grid: interfaces.renderers.TreeGrid) -> None:


class CSVRenderer(CLIRenderer):

name = "csv"
structured_output = True

Expand Down
5 changes: 3 additions & 2 deletions volatility3/cli/volshell/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,9 @@ def run(self):
raise ValueError(
"Invalid extension (extensions must be of the format \"conf.path.value='value'\")"
)
address, value = extension[: extension.find("=")], json.loads(
extension[extension.find("=") + 1 :]
address, value = (
extension[: extension.find("=")],
json.loads(extension[extension.find("=") + 1 :]),
)
ctx.config[address] = value

Expand Down
6 changes: 3 additions & 3 deletions volatility3/cli/volshell/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ def display_type(
and dereference_count < MAX_DEREFERENCE_COUNT
):
# before defreerencing the pointer, show it's information
print(f'{" " * dereference_count}{self._display_simple_type(volobject)}')
print(f"{' ' * dereference_count}{self._display_simple_type(volobject)}")

# check that we can follow the pointer before dereferencing and do not
# attempt to follow null pointers.
Expand All @@ -486,7 +486,7 @@ def display_type(

if hasattr(volobject.vol, "members"):
# display the header for this object, if the original object was just a type string, display the type information
struct_header = f'{" " * dereference_count}{volobject.vol.type_name} ({volobject.vol.size} bytes)'
struct_header = f"{' ' * dereference_count}{volobject.vol.type_name} ({volobject.vol.size} bytes)"
if isinstance(object, str) and offset is None:
suffix = ":"
else:
Expand Down Expand Up @@ -523,7 +523,7 @@ def display_type(
len_typename = len(member_type_name)
if len(member_type_name) > MAX_TYPENAME_DISPLAY_LENGTH:
len_typename = MAX_TYPENAME_DISPLAY_LENGTH
member_type_name = f"{member_type_name[:len_typename - 3]}..."
member_type_name = f"{member_type_name[: len_typename - 3]}..."

if isinstance(volobject, interfaces.objects.ObjectInterface):
# We're an instance, so also display the data
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
"""Volatility 3 framework."""

# Check the python version to ensure it's suitable
import glob
import sys
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/automagic/pdbscan.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
This module contains a standalone scanner, and also a :class:`~volatility3.framework.interfaces.layers.ScannerInterface`
based scanner for use within the framework by calling :func:`~volatility3.framework.interfaces.layers.DataLayerInterface.scan`.
"""

import contextlib
import logging
import math
Expand Down
5 changes: 3 additions & 2 deletions volatility3/framework/automagic/stacker.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,9 @@ def stack(
constructor(context, config_path, requirement)

# Stash the changed config items
self._cached = context.config.get(path, None), context.config.branch(
path
self._cached = (
context.config.get(path, None),
context.config.branch(path),
)
vollog.debug(
f"physical_layer maximum_address: {physical_layer.maximum_address}"
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/automagic/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
| x64 | 0x1ED |
+--------------+-------+
"""

import logging
import struct
from typing import Generator, Iterable, List, Optional, Tuple, Type
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/configuration/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
types (such as strings, integers, etc) as well as indicating what they
expect to be in the context (such as particular layers or symboltables).
"""

import abc
import logging
import os
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/constants/linux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

Linux-specific values that aren't found in debug symbols
"""

import enum
from dataclasses import dataclass

Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/contexts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
contexts, to allow a plugin to act on multiple different contexts
without them interfering with each other.
"""

import functools
import hashlib
import logging
Expand Down
2 changes: 1 addition & 1 deletion volatility3/framework/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def wrapper(*args, **kwargs):
"This is a bug, the deprecated call needs to be removed and the caller needs to update their code to use the new method.",
)

deprecation_msg = f"Method \"{deprecated_func.__module__ + '.' + deprecated_func.__qualname__}\" is deprecated and will be removed in the first release after {removal_date}, use \"{replacement.__module__ + '.' + replacement.__qualname__}\" instead. {additional_information}"
deprecation_msg = f'Method "{deprecated_func.__module__ + "." + deprecated_func.__qualname__}" is deprecated and will be removed in the first release after {removal_date}, use "{replacement.__module__ + "." + replacement.__qualname__}" instead. {additional_information}'
warnings.warn(deprecation_msg, FutureWarning)
# Return the wrapped function with its original arguments
return deprecated_func(*args, **kwargs)
Expand Down
3 changes: 2 additions & 1 deletion volatility3/framework/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:class:`PagedInvalidAddressException` contains information about the
size of the invalid page.
"""

from typing import Callable, Dict, Optional, Tuple

from volatility3.framework import interfaces
Expand Down Expand Up @@ -161,4 +162,4 @@ def __init__(
self.failure_reason = failure_reason

def __str__(self):
return f"{self.source_component.__module__+ '.' + self.source_component.__qualname__}: Version {self.target_version} dependency on {self.target_component.__module__+ '.' + self.target_component.__name__} {self.target_component.version} unmet."
return f"{self.source_component.__module__ + '.' + self.source_component.__qualname__}: Version {self.target_version} dependency on {self.target_component.__module__ + '.' + self.target_component.__name__} {self.target_component.version} unmet."
1 change: 1 addition & 0 deletions volatility3/framework/interfaces/automagic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Automagic objects attempt to automatically fill configuration values
that a user has not filled.
"""

import logging
from abc import ABCMeta
from typing import Any, List, Optional, Tuple, Type, Union
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/interfaces/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
`object`, which will construct a symbol on a layer at a particular
offset.
"""

import collections
import copy
from abc import ABCMeta, abstractmethod
Expand Down
1 change: 1 addition & 0 deletions volatility3/framework/interfaces/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
One layer may combine other layers, map data based on the data itself,
or map a procedure (such as decryption) across another layer of data.
"""

import collections.abc
import functools
import logging
Expand Down
Loading
Loading