From aedacea60317ff88526ec9ed9aa0648e259a8c44 Mon Sep 17 00:00:00 2001 From: David McDonald Date: Fri, 14 Mar 2025 21:08:17 -0500 Subject: [PATCH] Packaging: Refactor JSON data handling This changes the way that JSON resources required for plugins are handled within the volatility3 package. Instead of operating directly on paths, it uses Python's builtin `importlib.resources` module to identify a data directory with JSON files as a resource location. This greatly simplifies how resources are found within the plugins. References: https://docs.python.org/3/library/importlib.resources.html#module-importlib.resources --- volatility3/data/__init__.py | 0 .../windows => data}/sids_and_privileges.json | 0 .../plugins/windows/getservicesids.py | 25 ++++--------------- .../framework/plugins/windows/getsids.py | 22 +++------------- .../framework/plugins/windows/privileges.py | 25 ++++--------------- 5 files changed, 14 insertions(+), 58 deletions(-) create mode 100644 volatility3/data/__init__.py rename volatility3/{framework/plugins/windows => data}/sids_and_privileges.json (100%) diff --git a/volatility3/data/__init__.py b/volatility3/data/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/volatility3/framework/plugins/windows/sids_and_privileges.json b/volatility3/data/sids_and_privileges.json similarity index 100% rename from volatility3/framework/plugins/windows/sids_and_privileges.json rename to volatility3/data/sids_and_privileges.json diff --git a/volatility3/framework/plugins/windows/getservicesids.py b/volatility3/framework/plugins/windows/getservicesids.py index 19a73fba8..7dc992473 100644 --- a/volatility3/framework/plugins/windows/getservicesids.py +++ b/volatility3/framework/plugins/windows/getservicesids.py @@ -4,11 +4,11 @@ import hashlib import json import logging -import os import struct +from importlib import resources from typing import List -from volatility3.framework import renderers, interfaces, constants, exceptions +from volatility3.framework import renderers, interfaces, exceptions from volatility3.framework.configuration import requirements from volatility3.framework.layers import registry from volatility3.plugins.windows.registry import hivelist @@ -39,24 +39,9 @@ class GetServiceSIDs(interfaces.plugins.PluginInterface): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Find the sids json path (or raise error if its not in the plugin directory). - for plugin_dir in constants.PLUGINS_PATH: - sids_json_file_name = os.path.join( - plugin_dir, os.path.join("windows", "sids_and_privileges.json") - ) - if os.path.exists(sids_json_file_name): - break - else: - vollog.log( - constants.LOGLEVEL_VVV, - "sids_and_privileges.json file is missing plugin error", - ) - raise RuntimeError( - "The sids_and_privileges.json file missed from you plugin directory" - ) - - # Get service sids dictionary (we need only the service sids). - with open(sids_json_file_name) as file_handle: + with resources.open_text( + "volatility3.data", "sids_and_privileges.json" + ) as file_handle: self.servicesids = json.load(file_handle)["service sids"] @classmethod diff --git a/volatility3/framework/plugins/windows/getsids.py b/volatility3/framework/plugins/windows/getsids.py index 786dc3394..3b855598a 100644 --- a/volatility3/framework/plugins/windows/getsids.py +++ b/volatility3/framework/plugins/windows/getsids.py @@ -4,16 +4,15 @@ import json import logging import ntpath -import os import re from typing import List, Dict, Union +from importlib import resources from volatility3.framework import ( renderers, interfaces, objects, exceptions, - constants, layers, ) from volatility3.framework.configuration import requirements @@ -42,23 +41,10 @@ class GetSIDs(interfaces.plugins.PluginInterface): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - for plugin_dir in constants.PLUGINS_PATH: - sids_json_file_name = os.path.join( - plugin_dir, os.path.join("windows", "sids_and_privileges.json") - ) - if os.path.exists(sids_json_file_name): - break - else: - vollog.log( - constants.LOGLEVEL_VVV, - "sids_and_privileges.json file is missing plugin error", - ) - raise RuntimeError( - "The sids_and_privileges.json file missed from you plugin directory" - ) - # Get all the sids from the json file. - with open(sids_json_file_name) as file_handle: + with resources.open_text( + "volatility3.data", "sids_and_privileges.json" + ) as file_handle: sids_json_data = json.load(file_handle) self.servicesids = sids_json_data["service sids"] self.well_known_sids = sids_json_data["well known"] diff --git a/volatility3/framework/plugins/windows/privileges.py b/volatility3/framework/plugins/windows/privileges.py index e41915442..7628e693a 100644 --- a/volatility3/framework/plugins/windows/privileges.py +++ b/volatility3/framework/plugins/windows/privileges.py @@ -3,10 +3,10 @@ import json import logging -import os +from importlib import resources from typing import List -from volatility3.framework import renderers, interfaces, objects, exceptions, constants +from volatility3.framework import constants, exceptions, interfaces, objects, renderers from volatility3.framework.configuration import requirements from volatility3.plugins.windows import pslist @@ -22,24 +22,9 @@ class Privs(interfaces.plugins.PluginInterface): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Find the sids json path (or raise error if its not in the plugin directory). - for plugin_dir in constants.PLUGINS_PATH: - sids_json_file_name = os.path.join( - plugin_dir, os.path.join("windows", "sids_and_privileges.json") - ) - if os.path.exists(sids_json_file_name): - break - else: - vollog.log( - constants.LOGLEVEL_VVV, - "sids_and_privileges.json file is missing plugin error", - ) - raise RuntimeError( - "The sids_and_privileges.json file missed from you plugin directory" - ) - - # Get service sids dictionary (we need only the service sids). - with open(sids_json_file_name) as file_handle: + with resources.open_text( + "volatility3.data", "sids_and_privileges.json" + ) as file_handle: temp_json = json.load(file_handle)["privileges"] self.privilege_info = { int(priv_num): temp_json[priv_num] for priv_num in temp_json