exceptions: SymbolErrors now contain specific information

This commit is contained in:
Mike Auty
2019-11-13 19:27:00 +00:00
committed by ikelos
parent ce3f4fb134
commit 40fcdf9469
7 changed files with 70 additions and 34 deletions
+9 -8
View File
@@ -288,35 +288,36 @@ class CommandLine(interfaces.plugins.FileConsumerInterface):
if isinstance(excp, exceptions.InvalidAddressException):
if isinstance(excp, exceptions.SwappedInvalidAddressException):
print("\nVolatility was unable to read a requested page from swap:\n"
"{} in layer {}\n\n"
"{} in layer {}: {}\n\n"
"This is likely caused by:\n"
"\tNo suitable swap file having been provided (locate and provide the correct swap file)\n"
"\tAn intentionally invalid page (operating system protection)".format(
hex(excp.invalid_address), excp.layer_name))
hex(excp.invalid_address), excp.layer_name, excp))
elif isinstance(excp, exceptions.PagedInvalidAddressException):
print("\nVolatility was unable to read a requested page:\n"
"{} in layer {}\n\n"
"{} in layer {}: {}\n\n"
"This could be caused by:\n"
"\tMemory smear during acquisition (try re-acquiring if possible)\n"
"\tAn intentionally invalid page lookup (operating system protection)\n"
"\tA bug in the plugin/volatility (re-run with -vvv and file a bug)".format(
hex(excp.invalid_address), excp.layer_name))
hex(excp.invalid_address), excp.layer_name, excp))
else:
print("\nVolatility was unable to read a requested page:\n"
"{} in layer {}\n\n"
"{} in layer {}: {}\n\n"
"This could be caused by:\n"
"\tThe base memory file being incomplete (try re-acquiring if possible)\n"
"\tMemory smear during acquisition (try re-acquiring if possible)\n"
"\tAn intentionally invalid page lookup (operating system protection)\n"
"\tA bug in the plugin/volatility (re-run with -vvv and file a bug)".format(
hex(excp.invalid_address), excp.layer_name))
hex(excp.invalid_address), excp.layer_name, excp))
elif isinstance(excp, exceptions.SymbolError):
print("\nVolatility experienced a symbol-related issue:\n"
"{}\n\n"
"{}{}{}: {}\n\n"
"This is likely caused by:\n"
"\tAn invalid symbol table\n"
"\tA plugin requesting a bad symbol\n"
"\tA plugin requesting a symbol from the wrong table\n".format(excp))
"\tA plugin requesting a symbol from the wrong table\n".format(excp.table_name, constants.BANG,
excp.symbol_name, excp))
elif isinstance(excp, exceptions.SymbolSpaceError):
print("\nVolatility experienced an issue related to a symbol table:\n "
"{}\n\n"
+6 -1
View File
@@ -8,7 +8,7 @@ space or symbol tables, and by layers when an address is invalid. The
:class:`PagedInvalidAddressException` contains information about the
size of the invalid page.
"""
from typing import Dict
from typing import Dict, Optional
from volatility.framework import interfaces
@@ -30,6 +30,11 @@ class PluginRequirementException(VolatilityException):
class SymbolError(VolatilityException):
"""Thrown when a symbol lookup has failed."""
def __init__(self, symbol_name: Optional[str], table_name: Optional[str], *args) -> None:
super().__init__(*args)
self.symbol_name = symbol_name
self.table_name = table_name
class LayerException(VolatilityException):
"""Thrown when an error occurs dealing with memory and layers."""
+2 -2
View File
@@ -295,14 +295,14 @@ class NativeTableInterface(BaseSymbolTableInterface):
"""Class to distinguish NativeSymbolLists from other symbol lists."""
def get_symbol(self, name: str) -> SymbolInterface:
raise exceptions.SymbolError("NativeTables never hold symbols")
raise exceptions.SymbolError(name, self.name, "NativeTables never hold symbols")
@property
def symbols(self) -> Iterable[str]:
return []
def get_enumeration(self, name: str) -> objects.Template:
raise exceptions.SymbolError("NativeTables never hold enumerations")
raise exceptions.SymbolError(name, self.name, "NativeTables never hold enumerations")
@property
def enumerations(self) -> Iterable[str]:
+9 -3
View File
@@ -5,7 +5,7 @@ import functools
import logging
from typing import Any, ClassVar, Dict, List, Type
from volatility.framework import interfaces, exceptions
from volatility.framework import interfaces, exceptions, constants
vollog = logging.getLogger(__name__)
@@ -87,8 +87,14 @@ class ReferenceTemplate(interfaces.objects.Template):
"""Referenced symbols must be appropriately resolved before they can
provide information such as size This is because the size request has
no context within which to determine the actual symbol structure."""
raise exceptions.SymbolError("Template contains no information about its structure: {}".format(
self.vol.type_name))
type_name = self.vol.type_name.split(constants.BANG)
table_name = None
if len(type_name) == 2:
table_name = type_name[0]
symbol_name = type_name[-1]
raise exceptions.SymbolError(
symbol_name, table_name,
"Template contains no information about its structure: {}".format(self.vol.type_name))
size = property(_unresolved) # type: ClassVar[Any]
replace_child = _unresolved # type: ClassVar[Any]
@@ -43,11 +43,8 @@ class VirtMap(interfaces.plugins.PluginInterface):
raise
result = {} # type: Dict[str, List[Tuple[int, int]]]
try:
system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE')
large_page_size = (layer.page_size ** 2) // module.get_type("_MMPTE").size
except exceptions.SymbolError:
raise exceptions.SymbolError("Required structures not found")
system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE')
large_page_size = (layer.page_size ** 2) // module.get_type("_MMPTE").size
if module.has_symbol('MiVisibleState'):
symbol = module.get_symbol('MiVisibleState')
@@ -67,7 +64,7 @@ class VirtMap(interfaces.plugins.PluginInterface):
result = cls._enumerate_system_va_type(large_page_size, system_range_start, module,
visible_state.SystemVaType)
else:
raise exceptions.SymbolError("Required structures not found")
raise exceptions.SymbolError(None, module.name, "Required structures not found")
elif module.has_symbol('MiSystemVaType'):
system_range_start = module.object(object_type = "pointer",
offset = module.get_symbol("MmSystemRangeStart").address)
@@ -80,7 +77,7 @@ class VirtMap(interfaces.plugins.PluginInterface):
result = cls._enumerate_system_va_type(large_page_size, system_range_start, module, type_array)
else:
raise exceptions.SymbolError("Required structures not found")
raise exceptions.SymbolError(None, module.name, "Required structures not found")
return result
+18 -5
View File
@@ -127,8 +127,9 @@ class SymbolSpace(interfaces.symbols.SymbolSpaceInterface):
try:
return getattr(self._dict[table_name], get_function)(component_name)
except KeyError as e:
raise exceptions.SymbolError('Type {} references missing Type/Symbol/Enum: {}'.format(name, e))
raise exceptions.SymbolError("Malformed name: {}".format(name))
raise exceptions.SymbolError(component_name, table_name,
'Type {} references missing Type/Symbol/Enum: {}'.format(name, e))
raise exceptions.SymbolError(name, None, "Malformed name: {}".format(name))
def _iterative_resolve(self, traverse_list):
"""Iteratively resolves a type, populating linked child
@@ -169,7 +170,11 @@ class SymbolSpace(interfaces.symbols.SymbolSpaceInterface):
self._resolved[type_name] = self._weak_resolve(SymbolType.TYPE, type_name) # type: ignore
self._iterative_resolve([type_name])
if isinstance(self._resolved[type_name], objects.templates.ReferenceTemplate):
raise exceptions.SymbolError("Unresolvable symbol requested: {}".format(type_name))
table_name = None
index = type_name.find(constants.BANG)
if index > 0:
table_name, type_name = type_name[:index], type_name[index + 1:]
raise exceptions.SymbolError(type_name, table_name, "Unresolvable symbol requested: {}".format(type_name))
return self._resolved[type_name]
def get_symbol(self, symbol_name: str) -> interfaces.symbols.SymbolInterface:
@@ -189,7 +194,11 @@ class SymbolSpace(interfaces.symbols.SymbolSpaceInterface):
if old_resolved is not None:
self._resolved_symbols[symbol_name] = old_resolved
if not isinstance(retval, interfaces.symbols.SymbolInterface):
raise exceptions.SymbolError("Unresolvable Symbol: {}".format(symbol_name))
table_name = None
index = symbol_name.find(constants.BANG)
if index > 0:
table_name, symbol_name = symbol_name[:index], symbol_name[index + 1:]
raise exceptions.SymbolError(symbol_name, table_name, "Unresolvable Symbol: {}".format(symbol_name))
return retval
def get_enumeration(self, enum_name: str) -> interfaces.objects.Template:
@@ -197,7 +206,11 @@ class SymbolSpace(interfaces.symbols.SymbolSpaceInterface):
table."""
retval = self._weak_resolve(SymbolType.ENUM, enum_name)
if not isinstance(retval, interfaces.objects.Template):
raise exceptions.SymbolError("Unresolvable Enumeration: {}".format(enum_name))
table_name = None
index = enum_name.find(constants.BANG)
if index > 0:
table_name, enum_name = enum_name[:index], enum_name[index + 1:]
raise exceptions.SymbolError(enum_name, table_name, "Unresolvable Enumeration: {}".format(enum_name))
return retval
def _membership(self, member_type: SymbolType, name: str) -> bool:
+22 -8
View File
@@ -312,7 +312,7 @@ class Version1Format(ISFormatTable):
return self._symbol_cache[name]
symbol = self._json_object['symbols'].get(name, None)
if not symbol:
raise exceptions.SymbolError("Unknown symbol: {}".format(name))
raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name))
self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, address = symbol['address'])
return self._symbol_cache[name]
@@ -402,10 +402,12 @@ class Version1Format(ISFormatTable):
def get_enumeration(self, enum_name: str) -> interfaces.objects.Template:
"""Resolves an individual enumeration."""
if constants.BANG in enum_name:
raise exceptions.SymbolError("Enumeration for a different table requested: {}".format(enum_name))
raise exceptions.SymbolError(enum_name, self.name,
"Enumeration for a different table requested: {}".format(enum_name))
if enum_name not in self._json_object['enums']:
# Fall back to the natives table
raise exceptions.SymbolError("Enumeration not found in {} table: {}".format(self.name, enum_name))
raise exceptions.SymbolError(enum_name, self.name,
"Enumeration not found in {} table: {}".format(self.name, enum_name))
curdict = self._json_object['enums'][enum_name]
base_type = self.natives.get_type(curdict['base'])
# The size isn't actually used, the base-type defines it.
@@ -417,7 +419,13 @@ class Version1Format(ISFormatTable):
def get_type(self, type_name: str) -> interfaces.objects.Template:
"""Resolves an individual symbol."""
if constants.BANG in type_name:
raise exceptions.SymbolError("Symbol for a different table requested: {}".format(type_name))
table_name = None
index = type_name.find(constants.BANG)
if index > 0:
table_name, type_name = type_name[:index], type_name[index + 1:]
raise exceptions.SymbolError(
type_name, table_name,
"Symbol for a different table requested: {}".format(table_name + constants.BANG + type_name))
if type_name not in self._json_object['user_types']:
# Fall back to the natives table
return self.natives.get_type(self.name + constants.BANG + type_name)
@@ -463,13 +471,19 @@ class Version2Format(Version1Format):
def get_type(self, type_name: str) -> interfaces.objects.Template:
"""Resolves an individual symbol."""
if constants.BANG in type_name:
raise exceptions.SymbolError("Symbol for a different table requested: {}".format(type_name))
table_name = None
index = type_name.find(constants.BANG)
if index > 0:
table_name, type_name = type_name[:index], type_name[index + 1:]
raise exceptions.SymbolError(
type_name, table_name,
"Symbol for a different table requested: {}".format(table_name + constants.BANG + type_name))
if type_name not in self._json_object['user_types']:
# Fall back to the natives table
if type_name in self.natives.types:
return self.natives.get_type(self.name + constants.BANG + type_name)
else:
raise exceptions.SymbolError("Unknown symbol: {}".format(type_name))
raise exceptions.SymbolError(type_name, self.name, "Unknown symbol: {}".format(type_name))
curdict = self._json_object['user_types'][type_name]
members = {}
for member_name in curdict['fields']:
@@ -497,7 +511,7 @@ class Version3Format(Version2Format):
return self._symbol_cache[name]
symbol = self._json_object['symbols'].get(name, None)
if not symbol:
raise exceptions.SymbolError("Unknown symbol: {}".format(name))
raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name))
symbol_type = None
if 'type' in symbol:
symbol_type = self._interdict_to_template(symbol['type'])
@@ -549,7 +563,7 @@ class Version5Format(Version4Format):
return self._symbol_cache[name]
symbol = self._json_object['symbols'].get(name, None)
if not symbol:
raise exceptions.SymbolError("Unknown symbol: {}".format(name))
raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name))
symbol_type = None
if 'type' in symbol:
symbol_type = self._interdict_to_template(symbol['type'])