Symbols: Add support for metadata verification of symbol tables

This commit is contained in:
Mike Auty
2024-01-14 23:05:10 +00:00
parent 66a4fc92bb
commit 62366d4f6f
6 changed files with 613 additions and 5 deletions
+2 -2
View File
@@ -44,8 +44,8 @@ BANG = "!"
# We use the SemVer 2.0.0 versioning scheme
VERSION_MAJOR = 2 # Number of releases of the library with a breaking change
VERSION_MINOR = 5 # Number of changes that only add to the interface
VERSION_PATCH = 2 # Number of changes that do not change the interface
VERSION_MINOR = 6 # Number of changes that only add to the interface
VERSION_PATCH = 0 # Number of changes that do not change the interface
VERSION_SUFFIX = ""
# TODO: At version 2.0.0, remove the symbol_shift feature
+10 -1
View File
@@ -10,10 +10,12 @@ from typing import Generator, Iterator, List, Tuple
from volatility3.framework import (
class_subclasses,
constants,
exceptions,
interfaces,
renderers,
)
from volatility3.framework.configuration import requirements
from volatility3.framework.interfaces import plugins
from volatility3.framework.objects import utility
vollog = logging.getLogger(__name__)
@@ -495,7 +497,7 @@ class Kmsg_5_10_to_(ABCKmsg):
class Kmsg(interfaces.plugins.PluginInterface):
"""Kernel log buffer reader"""
_required_framework_version = (2, 0, 0)
_required_framework_version = (2, 6, 0)
_version = (1, 0, 2)
@@ -514,6 +516,13 @@ class Kmsg(interfaces.plugins.PluginInterface):
yield (0, values)
def run(self):
if not self.context.symbol_space.verify_table_versions(
"dwarf2json", lambda version, _: (not version) or version > (0, 4, 1)
):
raise exceptions.SymbolSpaceError(
"Invalid symbol table, please ensure the ISF table produced by dwarf2json was produced using a version > 0.4.1"
)
return renderers.TreeGrid(
[
("facility", str),
+48 -1
View File
@@ -4,9 +4,20 @@
import collections
import collections.abc
import datetime
import enum
import logging
from typing import Any, Dict, Iterable, Iterator, TypeVar, List
from typing import (
Any,
Callable,
Dict,
Iterable,
Iterator,
Optional,
Tuple,
TypeVar,
List,
)
from volatility3.framework import constants, exceptions, interfaces, objects
@@ -113,6 +124,42 @@ class SymbolSpace(interfaces.symbols.SymbolSpaceInterface):
self._resolved = {}
del self._dict[key]
def verify_table_versions(
self,
producer: str,
validator: Callable[[Optional[Tuple], Optional[datetime.datetime]], bool],
tables: List[str] = None,
) -> bool:
"""Verifies the producer metadata and version of tables
Args:
producer: String name of a table producer to have validation performed
validator: callable that takes an optional version and an optional datetime that returns False if table is invalid
Returns:
False if an invalid table was found or True if no invalid table was found
"""
if tables is None:
tables = self._dict.keys()
for table_name in tables:
table = self._dict[table_name]
if not table.producer:
vollog.debug(
f"Symbol table {table_name} could not be validated because no producer metadata was found"
)
continue
if table.producer.name == producer:
# Run the verification
if not validator(
table.producer.version,
table.producer.datetime,
):
vollog.debug(f"Symbol table {table_name} does not pass validator")
return False
else:
continue
return True
### Resolution functions
class UnresolvedTemplate(objects.templates.ReferenceTemplate):
@@ -183,6 +183,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
types = _construct_delegate_function("types", True)
enumerations = _construct_delegate_function("enumerations", True)
metadata = _construct_delegate_function("metadata", True)
producer = _construct_delegate_function("producer", True)
clear_symbol_cache = _construct_delegate_function("clear_symbol_cache")
get_type = _construct_delegate_function("get_type")
get_symbol = _construct_delegate_function("get_symbol")
@@ -372,6 +373,14 @@ class ISFormatTable(interfaces.symbols.SymbolTableInterface, metaclass=ABCMeta):
table."""
return None
@property
def producer(self) -> Optional["metadata.ProducerMetadata"]:
"""Returns a metadata object containing information about the symbol
table."""
return metadata.ProducerMetadata(
self._json_object.get("metadata", {}).get("producer", {})
)
def clear_symbol_cache(self) -> None:
"""Clears the symbol cache of the symbol table."""
self._symbol_cache.clear()
+41 -1
View File
@@ -2,9 +2,49 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
import datetime
import logging
from typing import Optional, Tuple, Union
from volatility3.framework import interfaces
from volatility3.framework import constants, interfaces
vollog = logging.getLogger(__name__)
class ProducerMetadata(interfaces.symbols.MetadataInterface):
"""Class to handle the Producer metadata from an ISF"""
@property
def name(self) -> Optional[str]:
return self._json_data.get("name", None)
@property
def version(self) -> Optional[Tuple[int]]:
"""Returns the version of the ISF file producer"""
version = self._json_data.get("version", None)
if not version:
return None
if all([x in "0123456789." for x in version]):
return tuple([int(x) for x in version.split(".")])
else:
vollog.log(
constants.LOGLEVEL_VVVV,
f"Metadata version contains unexpected characters: '{version}'",
)
@property
def datetime(self) -> Optional[datetime.datetime]:
"""Returns a timestamp for when the file was produced"""
if "datetime" not in self._json_data:
return None
try:
timestamp = datetime.datetime.strptime(
self._json_data["datetime"], "YYYY-MM-DD"
)
except (TypeError, ValueError):
vollog.debug("Invalid timestamp in producer information of symbol table")
return None
return timestamp
class WindowsMetadata(interfaces.symbols.MetadataInterface):
+503
View File
@@ -0,0 +1,503 @@
{
"$schema": "http://json-schema.org/schema#",
"id": "http://volatilityfoundation.org/intermediate-format/schema",
"title": "Symbol Container",
"type": "object",
"definitions": {
"metadata_producer": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string",
"pattern": "^[0-9]+.[0-9]+.[0-9]+$"
},
"datetime": {
"type": "string",
"format": "date-time"
}
},
"required":[
"name",
"version"
]
},
"metadata_windows_pe": {
"type": "object",
"properties": {
"major": {
"type": "integer"
},
"minor": {
"type": "integer"
},
"revision": {
"type": "integer"
},
"build": {
"type": "integer"
}
},
"additionalProperties": false,
"required": [
"major",
"minor",
"revision"
]
},
"metadata_windows_pdb": {
"type": "object",
"properties": {
"GUID": {
"type": "string"
},
"age": {
"type": "integer"
},
"database": {
"type": "string"
},
"machine_type": {
"type": "integer"
}
},
"additionalProperties": false,
"required": [
"GUID",
"age",
"database",
"machine_type"
]
},
"metadata_windows": {
"type": "object",
"properties": {
"pe": {
"$ref": "#/definitions/metadata_windows_pe"
},
"pdb": {
"$ref": "#/definitions/metadata_windows_pdb"
}
},
"additionalProperties": false
},
"metadata_nix": {
"type": "object",
"properties": {
"symbols": {
"type": "array",
"items": {
"$ref": "#/definitions/metadata_nix_item"
}
},
"types": {
"type": "array",
"items": {
"$ref": "#/definitions/metadata_nix_item"
}
}
},
"additionalProperties": false
},
"metadata_format": {
"type": "string",
"pattern": "^6.[0-9]+.[0-9]+$"
},
"metadata_nix_item": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"pattern": "^(dwarf|symtab|system-map)$"
},
"name": {
"type": "string"
},
"hash_type": {
"type": "string",
"pattern": "^(sha256)$"
},
"hash_value": {
"type": "string",
"pattern": "^[a-fA-F0-9]+$"
}
},
"additionalProperties": false
},
"element_metadata": {
"type": "object",
"oneOf": [
{
"properties": {
"format": {
"$ref": "#/definitions/metadata_format"
},
"producer": {
"$ref": "#/definitions/metadata_producer"
}
},
"required": [
"format"
],
"additionalProperties": false
},
{
"properties": {
"format": {
"$ref": "#/definitions/metadata_format"
},
"producer": {
"$ref": "#/definitions/metadata_producer"
},
"windows": {
"$ref": "#/definitions/metadata_windows"
}
},
"required": [
"format",
"windows"
],
"additionalProperties": false
},
{
"properties": {
"format": {
"$ref": "#/definitions/metadata_format"
},
"producer": {
"$ref": "#/definitions/metadata_producer"
},
"linux": {
"$ref": "#/definitions/metadata_nix"
}
},
"required": [
"format",
"linux"
],
"additionalProperties": false
},
{
"properties": {
"format": {
"$ref": "#/definitions/metadata_format"
},
"producer": {
"$ref": "#/definitions/metadata_producer"
},
"mac": {
"$ref": "#/definitions/metadata_nix"
}
},
"required": [
"format",
"mac"
],
"additionalProperties": false
}
]
},
"element_enum": {
"properties": {
"size": {
"type": "integer"
},
"base": {
"type": "string"
},
"constants": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
}
},
"required": [
"size",
"base",
"constants"
],
"additionalProperties": false
},
"element_symbol": {
"properties": {
"address": {
"type": "number"
},
"linkage_name": {
"type": "string"
},
"type": {
"$ref": "#/definitions/type_descriptor"
},
"constant_data": {
"type": "string",
"media": {
"binaryEncoding": "base64",
"readOnly": true
}
}
},
"required": [
"address"
],
"additionalProperties": false
},
"element_base_type": {
"properties": {
"size": {
"type": "integer"
},
"signed": {
"type": "boolean"
},
"kind": {
"type": "string",
"pattern": "^(void|int|float|char|bool)$"
},
"endian": {
"type": "string",
"pattern": "^(little|big)$"
}
},
"required": [
"size",
"kind",
"signed",
"endian"
],
"additionalProperties": false
},
"element_user_type": {
"properties": {
"kind": {
"type": "string",
"pattern": "^(struct|union|class)$"
},
"size": {
"type": "integer"
},
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/field"
}
}
},
"required": [
"kind",
"size",
"fields"
],
"additionalProperties": false
},
"field": {
"properties": {
"type": {
"$ref": "#/definitions/type_descriptor"
},
"offset": {
"type": "integer"
},
"anonymous": {
"type": "boolean"
}
},
"required": [
"type",
"offset"
],
"additionalProperties": false
},
"type_descriptor": {
"oneOf": [
{
"$ref": "#/definitions/type_pointer"
},
{
"$ref": "#/definitions/type_base"
},
{
"$ref": "#/definitions/type_array"
},
{
"$ref": "#/definitions/type_struct"
},
{
"$ref": "#/definitions/type_enum"
},
{
"$ref": "#/definitions/type_function"
},
{
"$ref": "#/definitions/type_bitfield"
}
]
},
"type_pointer": {
"properties": {
"kind": {
"type": "string",
"pattern": "^pointer$"
},
"base": {
"type": "string"
},
"subtype": {
"$ref": "#/definitions/type_descriptor"
}
},
"required": [
"kind",
"subtype"
],
"additionalProperties": false
},
"type_base": {
"properties": {
"kind": {
"type": "string",
"pattern": "^base$"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"additionalProperties": false
},
"type_array": {
"properties": {
"kind": {
"type": "string",
"pattern": "^array$"
},
"subtype": {
"$ref": "#/definitions/type_descriptor"
},
"count": {
"type": "integer"
}
},
"required": [
"kind",
"subtype",
"count"
],
"additionalProperties": false
},
"type_struct": {
"properties": {
"kind": {
"type": "string",
"pattern": "^(struct|class|union)$"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"additionalProperties": false
},
"type_enum": {
"properties": {
"kind": {
"type": "string",
"pattern": "^enum$"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"additionalProperties": false
},
"type_function": {
"properties": {
"kind": {
"type": "string",
"pattern": "^function$"
}
},
"required": [
"kind"
],
"additionalProperties": false
},
"type_bitfield": {
"properties": {
"kind": {
"type": "string",
"pattern": "^bitfield$"
},
"bit_position": {
"type": "integer"
},
"bit_length": {
"type": "integer"
},
"type": {
"oneOf": [
{
"$ref": "#/definitions/type_base"
},
{
"$ref": "#/definitions/type_enum"
}
]
}
},
"required": [
"kind",
"bit_position",
"bit_length",
"type"
],
"additionalProperties": false
}
},
"properties": {
"metadata": {
"$ref": "#/definitions/element_metadata"
},
"base_types": {
"additionalProperties": {
"$ref": "#/definitions/element_base_type"
}
},
"user_types": {
"additionalProperties": {
"$ref": "#/definitions/element_user_type"
}
},
"enums": {
"additionalProperties": {
"$ref": "#/definitions/element_enum"
}
},
"symbols": {
"additionalProperties": {
"$ref": "#/definitions/element_symbol"
}
}
},
"required": [
"metadata",
"base_types",
"user_types",
"enums",
"symbols"
],
"additionalProperties": false
}