diff --git a/volatility/framework/plugins/windows/info.py b/volatility/framework/plugins/windows/info.py index 0be9273db..7de4a7874 100644 --- a/volatility/framework/plugins/windows/info.py +++ b/volatility/framework/plugins/windows/info.py @@ -51,37 +51,107 @@ class Info(plugins.PluginInterface): # FileLayer won't have dependencies pass - def _generator(self): - - virtual_layer_name = self.config["primary"] - virtual_layer = self.context.layers[virtual_layer_name] + @classmethod + def get_kernel_module(cls, context: interfaces.context.ContextInterface, layer_name: str, symbol_table: str): + """Returns the kernel module based on the layer and symbol_table""" + virtual_layer = context.layers[layer_name] if not isinstance(virtual_layer, layers.intel.Intel): raise TypeError("Virtual Layer is not an intel layer") - native_types = self.context.symbol_space[self.config["nt_symbols"]].natives + kvo = virtual_layer.config["kernel_virtual_offset"] - kdbg_table_name = intermed.IntermediateSymbolTable.create(self.context, - self.config_path, + ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo) + return ntkrnlmp + + @classmethod + def get_kdbg_structure(cls, context: interfaces.context.ContextInterface, config_path: str, layer_name: str, + symbol_table: str) -> interfaces.objects.ObjectInterface: + """Returns the KDDEBUGGER_DATA64 structure for a kernel""" + ntkrnlmp = cls.get_kernel_module(context, layer_name, symbol_table) + + native_types = context.symbol_space[symbol_table].natives + + kdbg_offset = ntkrnlmp.get_symbol("KdDebuggerDataBlock").address + + kdbg_table_name = intermed.IntermediateSymbolTable.create(context, + interfaces.configuration.path_join( + config_path, 'kdbg'), "windows", "kdbg", native_types = native_types, class_types = extensions.kdbg.class_types) - pe_table_name = intermed.IntermediateSymbolTable.create(self.context, - self.config_path, + kdbg = context.object(kdbg_table_name + constants.BANG + "_KDDEBUGGER_DATA64", + offset = ntkrnlmp.offset + kdbg_offset, + layer_name = layer_name) + + return kdbg + + @classmethod + def get_kuser_structure(cls, context: interfaces.context.ContextInterface, layer_name: str, + symbol_table: str) -> interfaces.objects.ObjectInterface: + """Returns the _KUSER_SHARED_DATA structure for a kernel""" + virtual_layer = context.layers[layer_name] + if not isinstance(virtual_layer, layers.intel.Intel): + raise TypeError("Virtual Layer is not an intel layer") + + ntkrnlmp = cls.get_kernel_module(context, layer_name, symbol_table) + + # this is a hard-coded address in the Windows OS + if virtual_layer.bits_per_register == 32: + kuser_addr = 0xFFDF0000 + else: + kuser_addr = 0xFFFFF78000000000 + + kuser = ntkrnlmp.object(object_type = "_KUSER_SHARED_DATA", + layer_name = layer_name, + offset = kuser_addr, + absolute = True) + + return kuser + + @classmethod + def get_version_structure(cls, context: interfaces.context.ContextInterface, layer_name: str, + symbol_table: str) -> interfaces.objects.ObjectInterface: + """Returns the KdVersionBlock information from a kernel""" + ntkrnlmp = cls.get_kernel_module(context, layer_name, symbol_table) + + vers_offset = ntkrnlmp.get_symbol("KdVersionBlock").address + + vers = ntkrnlmp.object(object_type = "_DBGKD_GET_VERSION64", layer_name = layer_name, offset = vers_offset) + + return vers + + @classmethod + def get_ntheader_structure(cls, context: interfaces.context.ContextInterface, config_path: str, + layer_name: str) -> interfaces.objects.ObjectInterface: + """Gets the ntheader structure for the kernel of the specified layer""" + virtual_layer = context.layers[layer_name] + if not isinstance(virtual_layer, layers.intel.Intel): + raise TypeError("Virtual Layer is not an intel layer") + + kvo = virtual_layer.config["kernel_virtual_offset"] + + pe_table_name = intermed.IntermediateSymbolTable.create(context, + interfaces.configuration.path_join(config_path, 'pe'), "windows", "pe", class_types = extensions.pe.class_types) - kvo = virtual_layer.config["kernel_virtual_offset"] + dos_header = context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER", + offset = kvo, + layer_name = layer_name) - ntkrnlmp = self.context.module(self.config["nt_symbols"], layer_name = virtual_layer_name, offset = kvo) + nt_header = dos_header.get_nt_header() - kdbg_offset = ntkrnlmp.get_symbol("KdDebuggerDataBlock").address + return nt_header - kdbg = self.context.object(kdbg_table_name + constants.BANG + "_KDDEBUGGER_DATA64", - offset = kvo + kdbg_offset, - layer_name = virtual_layer_name) + def _generator(self): + + layer_name = self.config['primary'] + symbol_table = self.config['nt_symbols'] + + kdbg = self.get_kdbg_structure(self.context, self.config_path, layer_name, symbol_table) yield (0, ("Kernel Base", hex(self.config["primary.kernel_virtual_offset"]))) yield (0, ("DTB", hex(self.config["primary.page_map_offset"]))) @@ -96,34 +166,21 @@ class Info(plugins.PluginInterface): yield (0, ("NTBuildLab", kdbg.get_build_lab())) yield (0, ("CSDVersion", str(kdbg.get_csdversion()))) - vers_offset = ntkrnlmp.get_symbol("KdVersionBlock").address - - vers = ntkrnlmp.object(object_type = "_DBGKD_GET_VERSION64", - layer_name = virtual_layer_name, - offset = vers_offset) + vers = self.get_version_structure(self.context, layer_name, symbol_table) yield (0, ("KdVersionBlock", hex(vers.vol.offset))) yield (0, ("Major/Minor", "{0}.{1}".format(vers.MajorVersion, vers.MinorVersion))) yield (0, ("MachineType", str(vers.MachineType))) + ntkrnlmp = self.get_kernel_module(self.context, layer_name, symbol_table) + cpu_count_offset = ntkrnlmp.get_symbol("KeNumberProcessors").address - cpu_count = ntkrnlmp.object(object_type = "unsigned int", - layer_name = virtual_layer_name, - offset = cpu_count_offset) + cpu_count = ntkrnlmp.object(object_type = "unsigned int", layer_name = layer_name, offset = cpu_count_offset) yield (0, ("KeNumberProcessors", str(cpu_count))) - # this is a hard-coded address in the Windows OS - if virtual_layer.bits_per_register == 32: - kuser_addr = 0xFFDF0000 - else: - kuser_addr = 0xFFFFF78000000000 - - kuser = ntkrnlmp.object(object_type = "_KUSER_SHARED_DATA", - layer_name = virtual_layer_name, - offset = kuser_addr, - absolute = True) + kuser = self.get_kuser_structure(self.context, layer_name, symbol_table) yield (0, ("SystemTime", str(kuser.SystemTime.get_time()))) yield (0, ("NtSystemRoot", @@ -134,11 +191,7 @@ class Info(plugins.PluginInterface): # yield (0, ("KdDebuggerEnabled", "True" if kuser.KdDebuggerEnabled else "False")) # yield (0, ("SafeBootMode", "True" if kuser.SafeBootMode else "False")) - dos_header = self.context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER", - offset = kvo, - layer_name = virtual_layer_name) - - nt_header = dos_header.get_nt_header() + nt_header = self.get_ntheader_structure(self.context, self.config_path, layer_name) yield (0, ("PE MajorOperatingSystemVersion", str(nt_header.OptionalHeader.MajorOperatingSystemVersion))) yield (0, ("PE MinorOperatingSystemVersion", str(nt_header.OptionalHeader.MinorOperatingSystemVersion)))