mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-27 12:04:50 +02:00
119 lines
6.3 KiB
Python
119 lines
6.3 KiB
Python
import logging
|
|
from typing import Callable, Tuple, List, Optional
|
|
|
|
from volatility.framework import interfaces, constants, exceptions
|
|
|
|
vollog = logging.getLogger(__name__)
|
|
|
|
|
|
class OsDistinguisher:
|
|
"""Distinguishes a symbol table as being above a particular version or
|
|
point.
|
|
|
|
This will primarily check the version metadata first and foremost.
|
|
If that metadata isn't available then each item in the fallback_checks is tested.
|
|
If invert is specified then the result will be true if the version is less than that specified, or in the case of
|
|
fallback, if any of the fallback checks is successful.
|
|
|
|
A fallback check is made up of:
|
|
* a symbol or type name
|
|
* a member name (implying that the value before was a type name)
|
|
* whether that symbol, type or member must be present or absent for the symbol table to be more above the required point
|
|
|
|
Note:
|
|
Specifying that a member must not be present includes the whole type not being present too (ie, either will pass the test)
|
|
|
|
Args:
|
|
version_check: Function that takes a 4-tuple version and returns whether whether the provided version is above a particular point
|
|
fallback_checks: A list of symbol/types/members of types, and whether they must be present to be above the required point
|
|
|
|
Returns:
|
|
A function that takes a context and a symbol table name and determines whether that symbol table passes the distinguishing checks
|
|
"""
|
|
|
|
def __init__(self, version_check: Callable[[Tuple[int, ...]], bool], fallback_checks: List[Tuple[str, Optional[str],
|
|
bool]]):
|
|
self._version_check = version_check
|
|
self._fallback_checks = fallback_checks
|
|
|
|
# try the primary method based on the pe version in the ISF
|
|
def __call__(self, context: interfaces.context.ContextInterface, symbol_table: str) -> bool:
|
|
"""
|
|
|
|
Args:
|
|
context: The context that contains the symbol table named `symbol_table`
|
|
symbol_table: Name of the symbol table within the context to distinguish the version of
|
|
|
|
Returns:
|
|
True if the symbol table is of the required version
|
|
"""
|
|
|
|
try:
|
|
pe_version = context.symbol_space[symbol_table].metadata.pe_version
|
|
major, minor, revision, build = pe_version
|
|
return self._version_check((major, minor, revision, build))
|
|
except (AttributeError, ValueError, TypeError):
|
|
vollog.log(constants.LOGLEVEL_VVV, "Windows PE version data is not available")
|
|
|
|
# fall back to the backup method, if necessary
|
|
for name, member, response in self._fallback_checks:
|
|
if member is None:
|
|
if (context.symbol_space.has_symbol(symbol_table + constants.BANG + name)
|
|
or context.symbol_space.has_type(symbol_table + constants.BANG + name)) != response:
|
|
return False
|
|
else:
|
|
try:
|
|
symbol_type = context.symbol_space.get_type(symbol_table + constants.BANG + name)
|
|
if symbol_type.has_member(member) != response:
|
|
return False
|
|
except exceptions.SymbolError:
|
|
if not response:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
is_windows_8_1_or_later = OsDistinguisher(version_check = lambda x: x >= (6, 3),
|
|
fallback_checks = [("_KPRCB", "PendingTickFlags", True)])
|
|
|
|
is_vista_or_later = OsDistinguisher(version_check = lambda x: x >= (6, 0),
|
|
fallback_checks = [("KdCopyDataBlock", None, True)])
|
|
|
|
is_win10 = OsDistinguisher(version_check = lambda x: (10, 0) <= x,
|
|
fallback_checks = [("ObHeaderCookie", None, True), ("_HANDLE_TABLE", "HandleCount", False)])
|
|
|
|
is_windows_xp = OsDistinguisher(version_check = lambda x: (5, 1) <= x < (5, 2),
|
|
fallback_checks = [("KdCopyDataBlock", None, False),
|
|
("_HANDLE_TABLE", "HandleCount", True)])
|
|
|
|
is_xp_or_2003 = OsDistinguisher(version_check = lambda x: (5, 1) <= x < (6, 0),
|
|
fallback_checks = [("KdCopyDataBlock", None, False),
|
|
("_HANDLE_TABLE", "HandleCount", True)])
|
|
|
|
is_win10_up_to_15063 = OsDistinguisher(version_check = lambda x: (10, 0) <= x < (10, 0, 15063),
|
|
fallback_checks = [("ObHeaderCookie", None, True),
|
|
("_HANDLE_TABLE", "HandleCount", False),
|
|
("_EPROCESS", "KeepAliveCounter", True)])
|
|
|
|
is_win10_15063 = OsDistinguisher(version_check = lambda x: x == (10, 0, 15063),
|
|
fallback_checks = [("ObHeaderCookie", None, True),
|
|
("_HANDLE_TABLE", "HandleCount", False),
|
|
("_EPROCESS", "KeepAliveCounter", False),
|
|
("_EPROCESS", "ControlFlowGuardEnabled", True)])
|
|
|
|
is_win10_16299_or_later = OsDistinguisher(version_check = lambda x: x >= (10, 0, 16299),
|
|
fallback_checks = [("ObHeaderCookie", None, True),
|
|
("_HANDLE_TABLE", "HandleCount", False),
|
|
("_EPROCESS", "KeepAliveCounter", False),
|
|
("_EPROCESS", "ControlFlowGuardEnabled", False)])
|
|
|
|
is_windows_10 = OsDistinguisher(version_check = lambda x: x >= (10, 0),
|
|
fallback_checks = [("ObHeaderCookie", None, True)])
|
|
|
|
is_windows_8_or_later = OsDistinguisher(version_check = lambda x: x >= (6, 2),
|
|
fallback_checks = [("_HANDLE_TABLE", "HandleCount", False)])
|
|
# Technically, this is win7 or less
|
|
is_windows_7 = OsDistinguisher(version_check = lambda x: x == (6, 1),
|
|
fallback_checks = [("_OBJECT_HEADER", "TypeIndex", True),
|
|
("_HANDLE_TABLE", "HandleCount", True)])
|