From 471b19b037deab511bc7e9144bc5b25b47cfc81d Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 18 Feb 2023 21:05:05 +0000 Subject: [PATCH 1/3] Layers: Use ctypes for snappy support --- requirements-dev.txt | 4 ---- requirements.txt | 4 ---- volatility3/framework/layers/avml.py | 35 ++++++++++++++++++++++------ 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 7c372da2a..9db14d441 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -20,7 +20,3 @@ jsonschema>=2.3.0 # This is required for memory acquisition via leechcore/pcileech. leechcorepyc>=2.4.0 - -# This is required for analyzing Linux samples compressed using AVMLs native -# compression format. It is not required for AVML's standard LiME compression. -python-snappy==0.6.0 diff --git a/requirements.txt b/requirements.txt index 1793012f1..99e0786cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,3 @@ pycryptodome # This is required for memory acquisition via leechcore/pcileech. leechcorepyc>=2.4.0 - -# This is required for analyzing Linux samples compressed using AVMLs native -# compression format. It is not required for AVML's standard LiME compression. -python-snappy==0.6.0 diff --git a/volatility3/framework/layers/avml.py b/volatility3/framework/layers/avml.py index 66f3f0e4f..3ce25ca6f 100644 --- a/volatility3/framework/layers/avml.py +++ b/volatility3/framework/layers/avml.py @@ -6,6 +6,7 @@ The user of the file doesn't have to worry about the compression, but random access is not allowed.""" +import ctypes import logging import struct from typing import Tuple, List, Optional @@ -16,13 +17,35 @@ from volatility3.framework.layers import segmented vollog = logging.getLogger(__name__) try: - import snappy + from ctypes import cdll + + # TODO: Find library for windows if needed + lib_snappy = cdll.LoadLibrary("libsnappy.so.1") + __snappy_uncompress = lib_snappy.snappy_uncompress + __snappy_uncompressed_length = lib_snappy.snappy_uncompressed_length HAS_SNAPPY = True -except ImportError: +except OSError: HAS_SNAPPY = False +class SnappyException(Exception): + pass + + +def uncompress(s): + """Uncompress a snappy compressed string.""" + ulen = ctypes.c_int(0) + cresult = __snappy_uncompressed_length(s, len(s), ctypes.byref(ulen)) + if cresult != 0: + raise SnappyException(f"Error in snappy_uncompressed_length: {cresult}") + ubuf = ctypes.create_string_buffer(ulen.value) + __snappy_uncompress(s, len(s), ubuf, ctypes.byref(ulen)) + if cresult != 0: + raise SnappyException(f"Error in snappy_uncompress: {cresult}") + return ubuf.raw + + class AVMLLayer(segmented.NonLinearlySegmentedLayer): """A Lime format TranslationLayer. @@ -44,9 +67,7 @@ class AVMLLayer(segmented.NonLinearlySegmentedLayer): if magic not in [0x4C4D5641] or version != 2: raise exceptions.LayerException("File not completely in AVML format") if not HAS_SNAPPY: - vollog.warning( - "AVML file detected, but snappy python library not installed" - ) + vollog.warning("AVML file detected, but snappy library could not be found") raise exceptions.LayerException( "AVML format dependencies not satisfied (snappy)" ) @@ -131,7 +152,7 @@ class AVMLLayer(segmented.NonLinearlySegmentedLayer): ] if frame_type == 0x00: # Compressed data - frame_data = snappy.decompress(frame_data) + frame_data = uncompress(frame_data) # TODO: Verify CRC segments.append( ( @@ -156,7 +177,7 @@ class AVMLLayer(segmented.NonLinearlySegmentedLayer): ) -> bytes: start_offset, _, _, _ = self._find_segment(offset) if self._compressed[mapped_offset]: - decoded_data = snappy.decompress(data) + decoded_data = uncompress(data) else: decoded_data = data decoded_data = decoded_data[offset - start_offset :] From c7252e9707ac0fb96c5fd65036cf8a8ff4b96672 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 19 Feb 2023 10:03:23 +0000 Subject: [PATCH 2/3] Automagic: Handle snappy for windows. --- volatility3/framework/layers/avml.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/volatility3/framework/layers/avml.py b/volatility3/framework/layers/avml.py index 3ce25ca6f..83c10186f 100644 --- a/volatility3/framework/layers/avml.py +++ b/volatility3/framework/layers/avml.py @@ -20,7 +20,23 @@ try: from ctypes import cdll # TODO: Find library for windows if needed - lib_snappy = cdll.LoadLibrary("libsnappy.so.1") + try: + # Linux/Mac + lib_snappy = cdll.LoadLibrary("libsnappy.so.1") + except OSError: + lib_snappy = None + + try: + if not lib_snappy: + # Windows 64 + lib_snappy = cdll.LoadLibrary("snappy64") + except OSError: + lib_snappy = None + + if lib_snappy: + # Windows 32 + lib_snappy = cdll.LoadLibrary("snappy32") + __snappy_uncompress = lib_snappy.snappy_uncompress __snappy_uncompressed_length = lib_snappy.snappy_uncompressed_length @@ -29,7 +45,7 @@ except OSError: HAS_SNAPPY = False -class SnappyException(Exception): +class SnappyException(exceptions.VolatilityException): pass @@ -65,9 +81,12 @@ class AVMLLayer(segmented.NonLinearlySegmentedLayer): layer.read(layer.minimum_address, struct.calcsize(header_structure)), ) if magic not in [0x4C4D5641] or version != 2: - raise exceptions.LayerException("File not completely in AVML format") + raise exceptions.LayerException("File not in AVML format") if not HAS_SNAPPY: - vollog.warning("AVML file detected, but snappy library could not be found") + vollog.warning( + "AVML file detected, but snappy library could not be found\n" + "Please install the snappy from your distribution or https://google.github.io/snappy/." + ) raise exceptions.LayerException( "AVML format dependencies not satisfied (snappy)" ) From ad3773d89884650cba6573280588f29e14e6ba0e Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 19 Feb 2023 10:23:04 +0000 Subject: [PATCH 3/3] Automagic: Improve identified AVML CodeQL issues --- volatility3/framework/layers/avml.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/volatility3/framework/layers/avml.py b/volatility3/framework/layers/avml.py index 83c10186f..1ba564c61 100644 --- a/volatility3/framework/layers/avml.py +++ b/volatility3/framework/layers/avml.py @@ -17,25 +17,23 @@ from volatility3.framework.layers import segmented vollog = logging.getLogger(__name__) try: - from ctypes import cdll - # TODO: Find library for windows if needed try: # Linux/Mac - lib_snappy = cdll.LoadLibrary("libsnappy.so.1") + lib_snappy = ctypes.cdll.LoadLibrary("libsnappy.so.1") except OSError: lib_snappy = None try: if not lib_snappy: # Windows 64 - lib_snappy = cdll.LoadLibrary("snappy64") + lib_snappy = ctypes.cdll.LoadLibrary("snappy64") except OSError: lib_snappy = None if lib_snappy: # Windows 32 - lib_snappy = cdll.LoadLibrary("snappy32") + lib_snappy = ctypes.cdll.LoadLibrary("snappy32") __snappy_uncompress = lib_snappy.snappy_uncompress __snappy_uncompressed_length = lib_snappy.snappy_uncompressed_length @@ -56,7 +54,7 @@ def uncompress(s): if cresult != 0: raise SnappyException(f"Error in snappy_uncompressed_length: {cresult}") ubuf = ctypes.create_string_buffer(ulen.value) - __snappy_uncompress(s, len(s), ubuf, ctypes.byref(ulen)) + cresult = __snappy_uncompress(s, len(s), ubuf, ctypes.byref(ulen)) if cresult != 0: raise SnappyException(f"Error in snappy_uncompress: {cresult}") return ubuf.raw