From a4bb32d797ea0726292b77969ba42c6c5bb86c14 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sun, 3 Sep 2017 21:50:53 +0100 Subject: [PATCH] Rework the linux automagic to include utility functions for finding the ASLR and KASLR shifts. --- volatility/framework/automagic/linux.py | 94 ++++++++++++++++++++----- 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/volatility/framework/automagic/linux.py b/volatility/framework/automagic/linux.py index 1aeef86ab..fdb123be5 100644 --- a/volatility/framework/automagic/linux.py +++ b/volatility/framework/automagic/linux.py @@ -1,6 +1,6 @@ import logging -from volatility.framework import interfaces +from volatility.framework import interfaces, constants from volatility.framework.automagic import linux_symbol_cache from volatility.framework.layers import intel, scanners @@ -86,8 +86,31 @@ class LintelStacker(interfaces.automagic.StackerLayerInterface): if isinstance(layer, intel.Intel): return None + virtual_dtb = cls.determine_virtual_dtb(context, layer_name, progress_callback) + if virtual_dtb is not None: + new_layer_name = context.memory.free_layer_name("IntelLayer") + config_path = interfaces.configuration.path_join("IntelHelper", new_layer_name) + context.config[interfaces.configuration.path_join(config_path, "memory_layer")] = layer_name + + if virtual_dtb > 0xffffffff80000000: + layer_class = intel.Intel32e + else: + layer_class = intel.Intel + dtb = LinuxUtilities.virtual_to_physical_address(virtual_dtb) + context.config[interfaces.configuration.path_join(config_path, "page_map_offset")] = virtual_dtb + + layer = layer_class(context, config_path = config_path, name = new_layer_name) + if layer: + vollog.debug("DTB was found at: 0x{:0x}".format(virtual_dtb)) + return layer + + @classmethod + def determine_virtual_dtb(cls, context, layer_name, progress_callback = None): + layer = context.memory[layer_name] + swapper_pg_dirs = [] - for offset in layer.scan(scanner = scanners.RegExScanner(cls.linux_signature), context = context): + for offset in layer.scan(scanner = scanners.RegExScanner(cls.linux_signature), context = context, + progress_callback = progress_callback): swapper_pg_dir_text = context.memory[layer_name].read(offset, len(cls.linux_signature) + 20) swapper_pg_dir = int(swapper_pg_dir_text[ swapper_pg_dir_text.index(b"=") + 1:swapper_pg_dir_text.index(b"\n")], 16) @@ -95,23 +118,56 @@ class LintelStacker(interfaces.automagic.StackerLayerInterface): dtb = 0 if swapper_pg_dirs: - best_swapper_pg_dir = \ - list(reversed(sorted(set(swapper_pg_dirs), key = lambda x: swapper_pg_dirs.count(x))))[0] + dtb = list(reversed(sorted(set(swapper_pg_dirs), key = lambda x: swapper_pg_dirs.count(x))))[0] - if best_swapper_pg_dir > 0xffffffff80000000: - shift = 0xffffffff80000000 - layer_class = intel.Intel32e - else: - shift = 0xc0000000 - layer_class = intel.Intel - dtb = best_swapper_pg_dir - shift + return dtb + return None - new_layer_name = context.memory.free_layer_name("IntelLayer") - config_path = interfaces.configuration.path_join("IntelHelper", new_layer_name) - context.config[interfaces.configuration.path_join(config_path, "memory_layer")] = layer_name - context.config[interfaces.configuration.path_join(config_path, "page_map_offset")] = dtb - layer = layer_class(context, config_path = config_path, name = new_layer_name) - if layer: - vollog.debug("DTB was found at: 0x{:0x}".format(dtb)) - return layer +class LinuxUtilities(object): + """Class with multiple useful linux functions""" + + @classmethod + def find_aslr(cls, context, symbol_table, layer_name, progress_callback = None): + """Determines the virtual ASLR value""" + path_join = interfaces.configuration.path_join + # Find the symbol table's version of the DTB + swapper_pg_dir_name = symbol_table + constants.BANG + 'init_level4_pgt' + table_dtb = context.symbol_space.get_symbol(swapper_pg_dir_name).address + + # Find the image's version of the DTB + image_dtb = LintelStacker.determine_virtual_dtb(context, layer_name, progress_callback) + + # Subtract the actual from the supposed to get the shift + vaslr_shift = image_dtb - table_dtb + return vaslr_shift + + @classmethod + def find_kaslr(cls, context, symbol_table, layer_name, progress_callback = None): + """Determines the offset of the actual DTB in physical space and its symbol offset""" + init_task_symbol = symbol_table + constants.BANG + 'init_task' + table_dtb = context.symbol_space.get_symbol(init_task_symbol).address + swapper_signature = b"swapper/0\x00\x00\x00\x00\x00\x00" + module = context.module(symbol_table, layer_name, 0) + + for offset in context.memory[layer_name].scan(scanner = scanners.RegExScanner(swapper_signature), + context = context, progress_callback = progress_callback): + task_symbol = module.get_type('task_struct') + image_dtb = offset - task_symbol.members['comm'][0] + init_task = module.object(type_name = 'task_struct', offset = image_dtb) + if init_task.pid != 0: + continue + if init_task.thread_info.cast('unsigned int') != 0: + continue + # This we get for free + aslr_shift = init_task.files.cast('long long unsigned int') - module.get_symbol('init_files').address + kaslr_shift = image_dtb - cls.virtual_to_physical_address(table_dtb) + return kaslr_shift + return None + + @classmethod + def virtual_to_physical_address(cls, addr): + """Converts a virtual linux address to a physical one (does not account of ASLR)""" + if addr > 0xffffffff80000000: + return addr - 0xffffffff80000000 + return addr - 0xc0000000