Use a central bit of code to do the load and unload of cached linux banners.

This commit is contained in:
Mike Auty
2017-07-17 16:38:25 +01:00
parent f6a55876d0
commit 5ca4f8e788
2 changed files with 27 additions and 17 deletions
+3 -11
View File
@@ -1,8 +1,7 @@
import logging
import os
import pickle
from volatility.framework import interfaces, constants
from volatility.framework import interfaces
from volatility.framework.automagic import linux_symbol_cache
from volatility.framework.layers import intel, scanners
vollog = logging.getLogger(__name__)
@@ -14,8 +13,7 @@ class LinuxSymbolFinder(interfaces.automagic.AutomagicInterface):
def __init__(self, context, config_path):
super().__init__(context, config_path)
self._requirements = None
self._linux_banners = {}
self._load_linux_banners()
self._linux_banners = linux_symbol_cache.LinuxSymbolCache.load_linux_banners()
def __call__(self, context, config_path, requirement, progress_callback = None):
"""Searches for LinuxSymbolRequirements and attempt to populate them"""
@@ -35,12 +33,6 @@ class LinuxSymbolFinder(interfaces.automagic.AutomagicInterface):
self._banner_scan(context, path, requirement, context.config[physical_path],
progress_callback)
def _load_linux_banners(self):
if os.path.exists(constants.LINUX_BANNERS_PATH):
with open(constants.LINUX_BANNERS_PATH, "rb") as f:
# We use pickle over JSON because we're dealing with bytes objects
self._linux_banners.update(pickle.load(f))
def _banner_scan(self, context, config_path, requirement, layer_name, progress_callback = None):
"""Accepts a context, config_path and SymbolRequirement, with a constructed layer_name
and scans the layer for linux banners"""
@@ -2,6 +2,7 @@ import logging
import os
import pathlib
import pickle
from urllib import parse
from volatility.framework import interfaces, constants
from volatility.framework.symbols import intermed
@@ -12,16 +13,34 @@ vollog = logging.getLogger(__name__)
class LinuxSymbolCache(interfaces.automagic.AutomagicInterface):
"""Class to run through all Linux symbols tables and cache their banners"""
def __call__(self, context, config_path, configurable, progress_callback = None):
"""Runs the automagic over the configurable"""
# We only need to be called once, so no recursion necessary
@classmethod
def load_linux_banners(cls):
linuxbanners = {}
if os.path.exists(constants.LINUX_BANNERS_PATH):
with open(constants.LINUX_BANNERS_PATH, "rb") as f:
# We use pickle over JSON because we're dealing with bytes objects
linuxbanners.update(pickle.load(f))
# Remove possibilities that can't exist locally.
for banner in linuxbanners:
for path in linuxbanners[banner]:
url = parse.urlparse(path)
if url.scheme == 'file' and not os.path.exists(url.path):
vollog.log(constants.LOGLEVEL_V,
"Removing cached path {} for banner {}: files does not exist".format(path, banner))
linuxbanners[banner].remove(path)
return linuxbanners
@classmethod
def save_linux_banners(cls, linuxbanners):
with open(constants.LINUX_BANNERS_PATH, "wb") as f:
pickle.dump(linuxbanners, f)
def __call__(self, context, config_path, configurable, progress_callback = None):
"""Runs the automagic over the configurable"""
# We only need to be called once, so no recursion necessary
linuxbanners = self.load_linux_banners()
search_paths = constants.SYMBOL_BASEPATHS
cacheables = []
for path in search_paths:
@@ -58,5 +77,4 @@ class LinuxSymbolCache(interfaces.automagic.AutomagicInterface):
pass
# Rewrite the cached linuxbanners each run, since writing is faster than the cache validation portion
with open(constants.LINUX_BANNERS_PATH, "wb") as f:
pickle.dump(linuxbanners, f)
self.save_linux_banners(linuxbanners)