/usr/lib/python2.7/dist-packages/rekall/plugins/common/scanners.py is in python-rekall-core 1.6.0+dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | # Rekall Memory Forensics
# Copyright 2016 Google Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
__author__ = "Michael Cohen <scudette@google.com>"
"""A Common mixin for implementing plugins based on scanning."""
from rekall import addrspace
class BaseScannerPlugin(object):
"""A mixin that implements scanner memory region selectors.
Most scanners are very similar - they search for specific byte patterns over
some sections of memory, validate those and present the results. Depending
on the type of structures searched for, different regions of memory need to
be looked at.
This mixin attempts to present a common interface to all scanning plugins,
where users may select different regions using common selector options, and
those will be generated automatically.
The plugin may select a set of default regions to scan, which are most
relevant to the specific data searched for, but the user may override the
defaults at all times.
NOTE: This plugin must be mixed with the specific OS's ProcessFilter
implementation in order to bring in standard process selectors.
"""
__args = [
dict(name="scan_physical", default=False, type="Boolean",
help="Scan the physical address space only."),
dict(name="scan_kernel", default=False, type="Boolean",
help="Scan the entire kernel address space."),
# Process Scanning options.
dict(name="scan_process_memory", default=False, type="Boolean",
help="Scan all of process memory. Uses process selectors to "
"narrow down selections."),
]
scanner_defaults = {}
def scan_specification_requested(self):
"""Return True if the user requested any specific regions."""
for k, v in self.plugin_args.items():
if k.startswith("scan_") and v:
return True
return False
def generate_memory_ranges(self):
"""Parse the plugin args and generate memory ranges.
Yields rekall.addrspace.Run objects.
"""
if not self.scan_specification_requested():
# Copy the plugin defaults into the args.
for k in self.plugin_args:
if k.startswith("scan_"):
self.plugin_args[k] = self.scanner_defaults.get(k, False)
# Physical address space requested.
if self.plugin_args.scan_physical:
yield addrspace.Run(
start=0, end=self.session.physical_address_space.end(),
address_space=self.session.physical_address_space,
data=dict(type="PhysicalAS"))
# Scan all of the kernel address space.
if self.plugin_args.scan_kernel:
yield addrspace.Run(
start=0, end=self.session.kernel_address_space.end(),
address_space=self.session.kernel_address_space,
data=dict(type="KernelAS"))
# Scan the complete process memory, not including the kernel.
if self.plugin_args.scan_process_memory:
# We use direct inheritance here so we can support process
# selectors.
for task in self.filter_processes():
cc = self.session.plugins.cc()
with cc:
# Switch to the process address space.
cc.SwitchProcessContext(task)
end = self.session.GetParameter("highest_usermode_address")
resolver = self.session.address_resolver
for module in sorted(resolver.GetAllModules(),
key=lambda x: x.start):
# Skip modules in kernel space.
if module.start > end:
break
comment = "%s (%s), %s" % (
task.name, task.pid, module.name)
self.session.logging.info(
"Scanning %s (%s) in: %s [%#x-%#x]",
task.name, task.pid, comment,
module.start, module.end)
yield addrspace.Run(
start=module.start, end=module.end,
address_space=self.session.default_address_space,
data=dict(type=comment, module=module, task=task))
|