mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-28 20:44:52 +02:00
Symbols: Add support for metadata verification of symbol tables
This commit is contained in:
@@ -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,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),
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user