diff --git a/volatility3/cli/__init__.py b/volatility3/cli/__init__.py index 488892d37..e3fb726a1 100644 --- a/volatility3/cli/__init__.py +++ b/volatility3/cli/__init__.py @@ -423,7 +423,7 @@ class CommandLine: detail = f"{excp}" caused_by = ["A required python module is not installed (install the module and re-run)"] else: - general = "Volatilty encountered an unexpected situation." + general = "Volatility encountered an unexpected situation." detail = "" caused_by = [ "Please re-run using with -vvv and file a bug with the output", f"at {constants.BUG_URL}" diff --git a/volatility3/framework/plugins/windows/callbacks.py b/volatility3/framework/plugins/windows/callbacks.py index 352dba448..2195671df 100644 --- a/volatility3/framework/plugins/windows/callbacks.py +++ b/volatility3/framework/plugins/windows/callbacks.py @@ -11,7 +11,6 @@ from volatility3.framework.renderers import format_hints from volatility3.framework.symbols import intermed from volatility3.framework.symbols.windows import versions from volatility3.plugins.windows import ssdt -from volatility3.plugins.windows import svcscan vollog = logging.getLogger(__name__) @@ -28,7 +27,6 @@ class Callbacks(interfaces.plugins.PluginInterface): requirements.ModuleRequirement(name = 'kernel', description = 'Windows kernel', architectures = ["Intel32", "Intel64"]), requirements.PluginRequirement(name = 'ssdt', plugin = ssdt.SSDT, version = (1, 0, 0)), - requirements.PluginRequirement(name = 'svcscan', plugin = svcscan.SvcScan, version = (1, 0, 0)) ] @staticmethod @@ -111,30 +109,19 @@ class Callbacks(interfaces.plugins.PluginInterface): yield symbol_name, callback.Callback, None @classmethod - def list_registry_callbacks(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str, - callback_table_name: str) -> Iterable[Tuple[str, int, None]]: - """Lists all registry callbacks. - - Args: - context: The context to retrieve required elements (layers, symbol tables) from - layer_name: The name of the layer on which to operate - symbol_table: The name of the table containing the kernel symbols - callback_table_name: The nae of the table containing the callback symbols - - Yields: - A name, location and optional detail string + def _list_registry_callbacks_legacy(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str, + callback_table_name: str) -> Iterable[Tuple[str, int, None]]: + """ + Lists all registry callbacks from the old format via the CmpCallBackVector. """ kvo = context.layers[layer_name].config['kernel_virtual_offset'] ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) full_type_name = callback_table_name + constants.BANG + "_EX_CALLBACK_ROUTINE_BLOCK" - try: - symbol_offset = ntkrnlmp.get_symbol("CmpCallBackVector").address - symbol_count_offset = ntkrnlmp.get_symbol("CmpCallBackCount").address - except exceptions.SymbolError: - vollog.debug("Cannot find CmpCallBackVector or CmpCallBackCount") - return + symbol_offset = ntkrnlmp.get_symbol("CmpCallBackVector").address + symbol_count_offset = ntkrnlmp.get_symbol("CmpCallBackCount").address + callback_count = ntkrnlmp.object(object_type = "unsigned int", offset = symbol_count_offset) @@ -155,6 +142,62 @@ class Callbacks(interfaces.plugins.PluginInterface): if callback.Function != 0: yield "CmRegisterCallback", callback.Function, None + @classmethod + def _list_registry_callbacks_new(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str, + callback_table_name: str) -> Iterable[Tuple[str, int, None]]: + """ + Lists all registry callbacks via the CallbackListHead. + """ + + kvo = context.layers[layer_name].config['kernel_virtual_offset'] + ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) + full_type_name = callback_table_name + constants.BANG + "_CM_CALLBACK_ENTRY" + + symbol_offset = ntkrnlmp.get_symbol("CallbackListHead").address + symbol_count_offset = ntkrnlmp.get_symbol("CmpCallBackCount").address + + callback_count = ntkrnlmp.object(object_type = "unsigned int", offset = symbol_count_offset) + + if callback_count == 0: + return + + callback_list = ntkrnlmp.object(object_type = "_LIST_ENTRY", offset = symbol_offset) + for callback in callback_list.to_list(full_type_name, "Link"): + yield "CmRegisterCallbackEx", callback.Function, f"Altitude: {callback.Altitude.String}" + + @classmethod + def list_registry_callbacks(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str, + callback_table_name: str) -> Iterable[Tuple[str, int, None]]: + """Lists all registry callbacks. + + Args: + context: The context to retrieve required elements (layers, symbol tables) from + layer_name: The name of the layer on which to operate + symbol_table: The name of the table containing the kernel symbols + callback_table_name: The nae of the table containing the callback symbols + + Yields: + A name, location and optional detail string + """ + + kvo = context.layers[layer_name].config['kernel_virtual_offset'] + ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) + + if ntkrnlmp.has_symbol("CmpCallBackVector") and ntkrnlmp.has_symbol("CmpCallBackCount"): + yield from cls._list_registry_callbacks_legacy(context, layer_name, symbol_table, callback_table_name) + elif ntkrnlmp.has_symbol("CallbackListHead") and ntkrnlmp.has_symbol("CmpCallBackCount"): + yield from cls._list_registry_callbacks_new(context, layer_name, symbol_table, callback_table_name) + else: + symbols_to_check = ["CmpCallBackVector", "CmpCallBackCount", "CallbackListHead"] + vollog.debug("Failed to get registry callbacks!") + for symbol_name in symbols_to_check: + symbol_status = "does not exist" + if ntkrnlmp.has_symbol(symbol_name): + symbol_status = "exists" + vollog.debug(f"symbol {symbol_name} {symbol_status}.") + + return + @classmethod def list_bugcheck_reason_callbacks(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str, callback_table_name: str) -> Iterable[Tuple[str, int, str]]: diff --git a/volatility3/framework/symbols/windows/callbacks-x64.json b/volatility3/framework/symbols/windows/callbacks-x64.json index dbb6086df..87682cb92 100644 --- a/volatility3/framework/symbols/windows/callbacks-x64.json +++ b/volatility3/framework/symbols/windows/callbacks-x64.json @@ -8,6 +8,12 @@ "signed": false, "endian": "little" }, + "unsigned long long": { + "kind": "int", + "size": 8, + "signed": false, + "endian": "little" + }, "unsigned char": { "kind": "char", "size": 1, @@ -137,6 +143,43 @@ }, "kind": "struct", "size": 64 + }, + "_CM_CALLBACK_ENTRY": { + "fields": { + "Link": { + "type": { + "kind": "struct", + "name": "nt_symbols!_LIST_ENTRY" + }, + "offset": 0 + }, + "Cookie": { + "type": { + "kind": "base", + "name": "unsigned long long" + }, + "offset": 24 + }, + "Function": { + "type": { + "kind": "pointer", + "subtype": { + "kind": "base", + "name": "void" + } + }, + "offset": 40 + }, + "Altitude": { + "type": { + "kind": "struct", + "name": "nt_symbols!_UNICODE_STRING" + }, + "offset": 48 + } + }, + "kind": "struct", + "size": 64 } }, "metadata": { diff --git a/volatility3/framework/symbols/windows/callbacks-x86.json b/volatility3/framework/symbols/windows/callbacks-x86.json index cf0cb8b65..702b68a65 100644 --- a/volatility3/framework/symbols/windows/callbacks-x86.json +++ b/volatility3/framework/symbols/windows/callbacks-x86.json @@ -8,6 +8,12 @@ "signed": false, "endian": "little" }, + "unsigned long long": { + "kind": "int", + "size": 8, + "signed": false, + "endian": "little" + }, "unsigned char": { "kind": "char", "size": 1, @@ -137,6 +143,43 @@ }, "kind": "struct", "size": 28 + }, + "_CM_CALLBACK_ENTRY": { + "fields": { + "Link": { + "type": { + "kind": "struct", + "name": "nt_symbols!_LIST_ENTRY" + }, + "offset": 0 + }, + "Cookie": { + "type": { + "kind": "base", + "name": "unsigned long long" + }, + "offset": 16 + }, + "Function": { + "type": { + "kind": "pointer", + "subtype": { + "kind": "base", + "name": "void" + } + }, + "offset": 28 + }, + "Altitude": { + "type": { + "kind": "struct", + "name": "nt_symbols!_UNICODE_STRING" + }, + "offset": 32 + } + }, + "kind": "struct", + "size": 40 } }, "metadata": {