mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-12 20:57:39 +02:00
Rework the linux automagic to include utility functions for finding the ASLR and KASLR shifts.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user