From b5d532555c68f2b9676b391e72e5e3e6b7539375 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Sat, 8 Dec 2018 18:21:39 +0000 Subject: [PATCH] Convert the adhoc scanner into a layer scanner using sections. --- .../symbols/linux/extensions/__init__.py | 38 +++++++------------ volatility/plugins/linux/bash.py | 11 ++++-- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/volatility/framework/symbols/linux/extensions/__init__.py b/volatility/framework/symbols/linux/extensions/__init__.py index c24dfbf11..7760b028d 100644 --- a/volatility/framework/symbols/linux/extensions/__init__.py +++ b/volatility/framework/symbols/linux/extensions/__init__.py @@ -1,4 +1,5 @@ import collections.abc +import logging import typing import volatility.framework.objects.utility @@ -7,6 +8,9 @@ from volatility.framework import exceptions, objects, interfaces from volatility.framework.automagic import linux from volatility.framework.symbols import generic +vollog = logging.getLogger(__name__) + + # Keep these in a basic module, to prevent import cycles when symbol providers require them class module(generic.GenericIntelProcess): @@ -53,35 +57,21 @@ class task_struct(generic.GenericIntelProcess): # Add the constructed layer and return the name return self._add_process_layer(self._context, dtb, config_prefix, preferred_name) - # TODO - replace with layer scanner once merged into master - # right now is a placeholder used to power & test the bash plugin - def search_process_memory(self, context, config, proc_layer, layer_name, s, heap_only = False): - pagesize = 0x1000 - - for vma in self.mm.mmap_iter: + def get_process_memory_sections(self, heap_only: bool = False) -> \ + typing.Generator[typing.Tuple[int, int], None, None]: + """Returns a list of sections based on the memory manager's view of this task's virtual memory""" + for vma in self.mm.mmap_iter: start = int(vma.vm_start) - end = int(vma.vm_end) - + end = int(vma.vm_end) + if heap_only and not (start <= self.mm.brk and end >= self.mm.start_brk): continue else: - print("adding vma: {:x} {:x} | {:x} {:x}".format(start, self.mm.brk, end, self.mm.start_brk)) - - while start < end: - try: - data = proc_layer.read(start, pagesize) - except exceptions.InvalidAddressException: - start = start + 4096 - continue + # FIXME: Check if this actually needs to be printed out or not + vollog.info("adding vma: {:x} {:x} | {:x} {:x}".format(start, self.mm.brk, end, self.mm.start_brk)) + + yield (start, end - start) - # util.iterfind from vol2 - for x in s: - offset = data.find(x, 0) - while offset >= 0: - yield start + offset, "" - offset = data.find(x, offset + len(x)) - - start = start + pagesize class fs_struct(objects.Struct): def get_root_dentry(self): diff --git a/volatility/plugins/linux/bash.py b/volatility/plugins/linux/bash.py index 1caf282ac..f190e0ed1 100644 --- a/volatility/plugins/linux/bash.py +++ b/volatility/plugins/linux/bash.py @@ -8,6 +8,7 @@ import struct from volatility.framework import constants, renderers, symbols from volatility.framework.configuration import requirements from volatility.framework.interfaces import plugins +from volatility.framework.layers import scanners from volatility.framework.objects import utility from volatility.framework.symbols.linux.bash import BashIntermedSymbols from volatility.plugins.linux import pslist @@ -55,14 +56,16 @@ class Bash(plugins.PluginInterface): bang_addrs = [] # find '#' values on the heap - for address, _ in task.search_process_memory(self.context, self.config, proc_layer, proc_layer_name, - [str.encode("#")], heap_only = True): + for address in proc_layer.scan(self.context, + scanners.BytesScanner(b"#"), + sections = task.get_process_memory_sections(heap_only = True)): bang_addrs.append(struct.pack(pack_format, address)) history_entries = [] - for address, _ in task.search_process_memory(self.context, self.config, proc_layer, proc_layer_name, - bang_addrs, heap_only = True): + for address, _ in proc_layer.scan(self.context, + scanners.MultiStringScanner(bang_addrs), + sections = task.get_process_memory_sections(heap_only = True)): hist = self.context.object(bash_table_name + constants.BANG + "hist_entry", offset = address - ts_offset, layer_name = proc_layer_name)