Rework the linux automagic to include utility functions for finding the ASLR and KASLR shifts.

This commit is contained in:
Mike Auty
2017-09-03 21:51:11 +01:00
parent 6265fc4e2d
commit a4bb32d797
+75 -19
View File
@@ -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