diff --git a/AUTHORS.txt b/AUTHORS.txt index c854a38bc..ee99a6cdd 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -1,3 +1,7 @@ +Rekall 1.0 Authors: +Michael Cohen +Johannes Stuettgen + Volatility 2.0 authors: Mike Auty @@ -17,7 +21,7 @@ Brendan Dolan-Gavitt Volatools Basic authors: -AAron Walters +AAron Walters Komoku, Inc. Nick L. Petroni, Jr. diff --git a/CHANGELOG.txt b/CHANGELOG.txt deleted file mode 100644 index 5b984b435..000000000 --- a/CHANGELOG.txt +++ /dev/null @@ -1,5 +0,0 @@ -Changelog - -As of Volatility 2.0, all changes are now tracked on the Google Code site: - -https://code.google.com/p/volatility/updates/list diff --git a/CREDITS.txt b/CREDITS.txt index d2262034b..d8c8f3f7f 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1,9 +1,5 @@ -Volatility 2.0 Contributors (alphabetical): ------------- - -We would like to acknowledge individuals that have made significant -contributions, code and ideas, to the 2.0 release of the -Volatility Framework 2.0: +The Rekall project would like to thank the following people for significant +contributions during the development of the project: Mike Auty Andrew Case @@ -12,28 +8,21 @@ Brendan Dolan-Gavitt Michael Hale Ligh Jamie Levy AAron Walters - -Volatility 1.3 Contributors (alphabetical) ------------- - -We would like to acknowledge individuals that have made significant -contributions, code and ideas, to the Volatility Framework: - Harlan Carvey Michael Cohen David Collett -Brendan Dolan-Gavitt +Brendan Dolan-Gavitt Andreas Schuster Matthieu Suiche -We would also like to acknowledge those who have provided valuable -feedback, bug reports, and testing: +We would also like to acknowledge those who have provided valuable feedback, bug +reports, and testing: Jide Abu Joseph Ayo Akinyele Tommaso Assandri Richard Austin -Frank Boldewin +Frank Boldewin Cameron C Caffee Eoghan Casey Angelo Cavallini diff --git a/LEGAL.txt b/LEGAL.txt index 25423d626..385863fd7 100644 --- a/LEGAL.txt +++ b/LEGAL.txt @@ -1,17 +1,18 @@ -Volatility -=============== +Rekall Memory Forensic Framework +================================ License ------- Copyright (C) 2007-2011 Volatile Systems +Copyright 2013 Google Inc. All Rights Reserved. -Volatility is free software; you can redistribute it and/or +Rekall 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. -Volatility is distributed in the hope that it will be useful, +Rekall 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. diff --git a/MANIFEST.in b/MANIFEST.in index 661cf5bd6..ca3f21728 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,12 +1 @@ -include *.txt -include *.win -include MANIFEST.in -include setup.py -include resources/* -include pyinstaller/*.py -include volatility/*.py -include contrib/plugins/*.py -include tools/*.py -include vol.py -include Makefile -include volatility.spec +include profiles/* \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index e7ff2f9cb..000000000 --- a/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: build - -build: - python setup.py build - -install: - python setup.py install - -dist: - python setup.py sdist - -clean: - rm -f `find . -name "*.pyc" -o -name "*~"` - rm -rf dist build diff --git a/PKG-INFO b/PKG-INFO deleted file mode 100644 index 64e8bb98f..000000000 --- a/PKG-INFO +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: Volatility -Version: GC1 -Summary: Volatility -- Volatile memory framwork -Home-page: http://www.volatilesystems.com -Author: AAron Walters -Author-email: awalters@volatilesystems.com -License: GPL -Description: UNKNOWN -Platform: UNKNOWN diff --git a/README.txt b/README.txt index 0357a7364..881195dc6 100644 --- a/README.txt +++ b/README.txt @@ -1,236 +1,44 @@ -============================================================================ -Volatility Framework - Volatile memory extraction utility framework -============================================================================ +================================ +Rekall Memory Forensic Framework +================================ -The Volatility Framework is a completely open collection of tools, -implemented in Python under the GNU General Public License, for the -extraction of digital artifacts from volatile memory (RAM) samples. -The extraction techniques are performed completely independent of the -system being investigated but offer visibilty into the runtime state -of the system. The framework is intended to introduce people to the -techniques and complexities associated with extracting digital artifacts -from volatile memory samples and provide a platform for further work into -this exciting area of research. +The Rekall Framework is a completely open collection of tools, implemented in +Python under the GNU General Public License, for the extraction of digital +artifacts from volatile memory (RAM) samples. The extraction techniques are +performed completely independent of the system being investigated but offer +visibilty into the runtime state of the system. The framework is intended to +introduce people to the techniques and complexities associated with extracting +digital artifacts from volatile memory samples and provide a platform for +further work into this exciting area of research. -The Volatility distribution is available from: -https://www.volatilesystems.com/default/volatility +The Rekall distribution is available from: +https://code.google.com/p/rekall/ -Volatility should run on any platform that supports +Rekall should run on any platform that supports Python (http://www.python.org) -Volatility supports investigations of the following x86 bit memory images: +Rekall supports investigations of the following x86 bit memory images: * Microsoft Windows XP Service Pack 2 and 3 -* Microsoft Windows 2003 Server Service Pack 0, 1 and 2 -* Microsoft Vista Service Pack 0, 1 and 2 -* Microsoft 2008 Server Service Pack 1 and 2 (there is no SP 0) * Microsoft Windows 7 Service Pack 0 and 1 +* Linux Kernels 2.6.24 to 3.10. -Volatility does not provide memory sample acquisition -capabilities. For acquisition, there are both free and commercial -solutions available. If you would like suggestions about suitable -acquisition solutions, please contact us at: - -volatility (at) volatilesystems (dot) com - -Volatility currently provides the following extraction capabilities for -memory samples: - - - Image date and time - - Running processes - - Open network sockets - - Open network connections - - DLLs loaded for each process - - Open files for each process - - Open registry keys for each process - - OS kernel modules - - Mapping physical offsets to virtual addresses - - Virtual Address Descriptor information - - Addressable memory for each process - - Memory maps for each process - - Extract executable samples - - Scanning examples: processes, threads, - sockets, connections, modules - -Volatility also supports a variety of sample file formats and the -ability to convert between these formats: - - - Raw linear sample (dd) - - Hibernation file - - Crash dump file - -Example Data -============ - -If you want to give Volatility a try, you can download exemplar -data hosted by NIST at the following url: - - http://www.cfreds.nist.gov/mem/memory-images.rar - -Links to other public memory images can be found at the following url: - - http://code.google.com/p/volatility/wiki/FAQ +Rekall also provides a complete memory sample acquisition capability for all +major operating systems (see the tools directory). Mailing Lists ============= -Mailing lists to support the users and developers of Volatility +Mailing lists to support the users and developers of Rekall can be found at the following address: - http://lists.volatilesystems.com/mailman/listinfo - -Contact -======= -For information or requests, contact: - -Volatile Systems - -Web: http://www.volatilesystems.com/ - http://volatility.tumblr.com/ - -Email: volatility (at) volatilesystems (dot) com - -IRC: #volatility on freenode - -Requirements -============ -- Python 2.6 or later, but not 3.0. http://www.python.org - -Some plugins may have other requirements which can be found at: - http://code.google.com/p/volatility/wiki/FAQ - -Quick Start -=========== -1. Unpack the latest version of Volatility from - https://www.volatilesystems.com/default/volatility - -2. To see available options, run "python vol.py -h" - - Example: - -> python vol.py -h -Volatile Systems Volatility Framework 2.0 -Usage: Volatility - A memory forensics analysis platform. - -Options: - -h, --help list all available options and their default values. - Default values may be set in the configuration file - (/etc/volatilityrc) - --conf-file=/Users/user/.volatilityrc - User based configuration file - -d, --debug Debug volatility - --info Print information about all registered objects - --plugins=PLUGINS Additional plugin directories to use (colon separated) - --cache-directory=/Users/user/.cache/volatility - Directory where cache files are stored - --no-cache Disable caching - --tz=TZ Sets the timezone for displaying timestamps - -f FILENAME, --filename=FILENAME - Filename to use when opening an image - -k KPCR, --kpcr=KPCR Specify a specific KPCR address - --output=text Output in this format (format support is module - specific) - --output-file=OUTPUT_FILE - write output in this file - -v, --verbose Verbose information - -g KDBG, --kdbg=KDBG Specify a specific KDBG virtual address - --dtb=DTB DTB Address - --cache-dtb Cache virtual to physical mappings - --use-old-as Use the legacy address spaces - -w, --write Enable write support - --profile=WinXPSP2x86 - Name of the profile to load - -l LOCATION, --location=LOCATION - A URN location from which to load an address space - - Supported Plugin Commands: - - bioskbd Reads the keyboard buffer from Real Mode memory - connections Print list of open connections [Windows XP Only] - connscan2 Scan Physical memory for _TCPT_OBJECT objects (tcp connections) - crashinfo Dump crash-dump information - dlldump Dump DLLs from a process address space - dlllist Print list of loaded dlls for each process - driverscan Scan for driver objects _DRIVER_OBJECT - files Print list of open files for each process - filescan Scan Physical memory for _FILE_OBJECT pool allocations - getsids Print the SIDs owning each process - hashdump Dumps passwords hashes (LM/NTLM) from memory - hibdump Dumps the hibernation file to a raw file - hibinfo Dump hibernation file information - hivedump Prints out a hive - hivelist Print list of registry hives. - hivescan Scan Physical memory for _CMHIVE objects (registry hives) - imagecopy Copies a physical address space out as a raw DD image - imageinfo Identify information for the image - inspectcache Inspect the contents of a cache - kdbgscan Search for and dump potential KDBG values - kpcrscan Search for and dump potential KPCR values - lsadump Dump (decrypted) LSA secrets from the registry - memdump Dump the addressable memory for a process - memmap Print the memory map - moddump Dump a kernel driver to an executable file sample - modscan2 Scan Physical memory for _LDR_DATA_TABLE_ENTRY objects - modules Print list of loaded modules - mutantscan Scan for mutant objects _KMUTANT - netscan Scan a Vista, 2008 or Windows 7 image for connections and sockets - patcher Patches memory based on page scans - printkey Print a registry key, and its subkeys and values - procexedump Dump a process to an executable file sample - procmemdump Dump a process to an executable memory sample - pslist print all running processes by following the EPROCESS lists - psscan Scan Physical memory for _EPROCESS objects - psscan2 Scan Physical memory for _EPROCESS pool allocations - pstree Print process list as a tree - regobjkeys Print list of open regkeys for each process - sockets Print list of open sockets - sockscan Scan Physical memory for _ADDRESS_OBJECT objects (tcp sockets) - ssdt Display SSDT entries - strings Match physical offsets to virtual addresses (may take a while, VERY verbose) - testsuite Run unit test suit using the Cache - thrdscan2 Scan physical memory for _ETHREAD objects - vaddump Dumps out the vad sections to a file - vadinfo Dump the VAD info - vadtree Walk the VAD tree and display in tree format - vadwalk Walk the VAD tree - volshell Shell in the memory image - -3. To get more information on a sample and to make sure Volatility - supports that sample type, run 'python vol.py imageinfo -f ' - - Example: - - > python vol.py -f win7.dmp imageinfo - Volatile Systems Volatility Framework 2.0 - Determining profile based on KDBG search... - Suggested Profile : Win7SP0x86 - AS Layer1 : JKIA32PagedMemory (Kernel AS) - AS Layer2 : FileAddressSpace (/Users/M/Desktop/win7.dmp) - PAE type : No PAE - DTB : 0x185000 - KDBG : 0x8296cbe8 - KPCR : 0x8296dc00 - KUSER_SHARED_DATA : 0xffdf0000 - Image date and time : 2010-07-06 22:40:28 - Image local date and time : 2010-07-06 22:40:28 - Image Type : - -4. Run some other tools. -f is a required option for all tools. Some - also require/accept other options. Run "python vol.py -h" for - more information on a particular command. A Command Reference wiki - is also available on the Google Code site: - - http://code.google.com/p/volatility/wiki/CommandReference - - as well as Basic Usage: - - http://code.google.com/p/volatility/wiki/BasicUsage - + rekall-discuss@googlegroups.com Licensing and Copyright ======================= Copyright (C) 2007-2011 Volatile Systems +Copyright 2013 Google Inc. All Rights Reserved. All Rights Reserved @@ -246,56 +54,30 @@ 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 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Bugs and Support ================ -There is no support provided with Volatility. There is NO +There is no support provided with Rekall. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. +PURPOSE. If you think you've found a bug, please report it at: - http://code.google.com/p/volatility/issues + http://code.google.com/p/rekall/issues In order to help us solve your issues as quickly as possible, please include the following information when filing a bug: -* The version of volatility you're using -* The operating system used to run volatility -* The version of python used to run volatility +* The version of rekall you're using +* The operating system used to run rekall +* The version of python used to run rekall * The suspected operating system of the memory image -* The complete command line you used to run volatility - -Depending on the operating system of the memory image, you may need to provide -additional information, such as: - -For Windows: -* The suspected Service Pack of the memory image - -For Linux: -* The suspected kernel version of the memory image - -Other options for communicaton can be found at: - http://code.google.com/p/volatility/wiki/FAQ - -Missing or Truncated Information -================================ -Volatile Systems makes no claims about the validity or correctness of the -output of Volatility. Many factors may contribute to the -incorrectness of output from Volatility including, but not -limited to, malicious modifications to the operating system, -incomplete information due to swapping, and information corruption on -image acquisition. - - -Command Reference -==================== -The following url contains a reference of all commands supported by -Volatility. - - http://code.google.com/p/volatility/wiki/CommandReference +* The complete command line you used to run rekall +More documentation +================== +Further documentation is available in the doc/ directory of this distribution. diff --git a/contrib/plugins/example.py b/contrib/plugins/example.py deleted file mode 100644 index f1f8c7a1b..000000000 --- a/contrib/plugins/example.py +++ /dev/null @@ -1,66 +0,0 @@ -# Volatility -# -# Authors: -# Mike Auty -# -# 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 -# - -import volatility.timefmt as timefmt -import volatility.obj as obj -import volatility.utils as utils -import volatility.commands as commands - -#pylint: disable-msg=C0111 - -class DateTime(commands.command): - """A simple example plugin that gets the date/time information from a Windows image""" - def calculate(self): - """Calculate and carry out any processing that may take time upon the image""" - # Load the address space - addr_space = utils.load_as(self._config) - - # Call a subfunction so that it can be used by other plugins - return self.get_image_time(addr_space) - - def get_image_time(self, addr_space): - """Extracts the time and date from the KUSER_SHARED_DATA area""" - # Get the Image Datetime - result = {} - - # Create a VOLATILITY_MAGIC object to look up the location of certain constants - # Get the KUSER_SHARED_DATA location - KUSER_SHARED_DATA = obj.VolMagic(addr_space).KUSER_SHARED_DATA.v() - # Create the _KUSER_SHARED_DATA object at the appropriate offset - k = obj.Object("_KUSER_SHARED_DATA", - offset = KUSER_SHARED_DATA, - vm = addr_space) - - # Start reading members from it - result['ImageDatetime'] = k.SystemTime - result['ImageTz'] = timefmt.OffsetTzInfo(-k.TimeZoneBias.as_windows_timestamp() / 10000000) - - # Return any results we got - return result - - def render_text(self, outfd, data): - """Renders the calculated data as text to outfd""" - # Convert the result into a datetime object for display in local and non local format - dt = data['ImageDatetime'].as_datetime() - - # Display the datetime in UTC as taken from the image - outfd.write("Image date and time : {0}\n".format(data['ImageDatetime'])) - # Display the datetime taking into account the timezone of the image itself - outfd.write("Image local date and time : {0}\n".format(timefmt.display_datetime(dt, data['ImageTz']))) diff --git a/contrib/plugins/psdispscan.py b/contrib/plugins/psdispscan.py deleted file mode 100644 index c450915f0..000000000 --- a/contrib/plugins/psdispscan.py +++ /dev/null @@ -1,182 +0,0 @@ -# Volatility -# -# Authors: -# Michael Cohen -# -# 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 -# - -""" -This module implements the slow thorough process scanning - -@author: Michael Cohen -@license: GNU General Public License 2.0 or later -@contact: scudette@users.sourceforge.net -@organization: Volatile Systems -""" - -#pylint: disable-msg=C0111 - -import volatility.commands as commands -import volatility.cache as cache -import volatility.utils as utils -import volatility.obj as obj -import volatility.scan as scan - -class DispatchHeaderCheck(scan.ScannerCheck): - """ A very fast check for an _EPROCESS.Pcb.Header. - - This check assumes that the type and size of - _EPROCESS.Pcb.Header are unsigned chars, but allows their - offsets to be determined from vtypes (so they could change - between OS versions). - """ - order = 10 - - def __init__(self, address_space, **_kwargs): - ## Because this checks needs to be super fast we first - ## instantiate the _EPROCESS and work out the offsets of the - ## type and size members. Then in the check we just read those - ## offsets directly. - eprocess = obj.Object("_EPROCESS", vm = address_space, offset = 0) - self.type = eprocess.Pcb.Header.Type - self.size = eprocess.Pcb.Header.Size - self.buffer_size = max(self.size.obj_offset, self.type.obj_offset) + 2 - scan.ScannerCheck.__init__(self, address_space) - - def check(self, offset): - data = self.address_space.read(offset + self.type.obj_offset, self.buffer_size) - return data[self.type.obj_offset] == "\x03" and data[self.size.obj_offset] == "\x1b" - - def skip(self, data, offset): - try: - nextval = data.index("\x03", offset + 1) - return nextval - self.type.obj_offset - offset - except ValueError: - ## Substring is not found - skip to the end of this data buffer - return len(data) - offset - -class CheckThreadList(scan.ScannerCheck): - """ Checks that _EPROCESS thread list points to the kernel Address Space """ - def check(self, offset): - eprocess = obj.Object("_EPROCESS", vm = self.address_space, - offset = offset) - kernel = 0x80000000 - - list_head = eprocess.ThreadListHead - - if list_head.Flink > kernel and \ - list_head.Blink > kernel: - return True - -class CheckDTBAligned(scan.ScannerCheck): - """ Checks that _EPROCESS.Pcb.DirectoryTableBase is aligned to 0x20 """ - def check(self, offset): - eprocess = obj.Object("_EPROCESS", vm = self.address_space, - offset = offset) - - return eprocess.Pcb.DirectoryTableBase % 0x20 == 0 - -class CheckSynchronization(scan.ScannerCheck): - """ Checks that _EPROCESS.WorkingSetLock and _EPROCESS.AddressCreationLock look valid """ - def check(self, offset): - eprocess = obj.Object("_EPROCESS", vm = self.address_space, - offset = offset) - - event = eprocess.WorkingSetLock.Event.Header - if event.Type != 0x1 or event.Size != 0x4: - return False - - event = eprocess.AddressCreationLock.Event.Header - if event.Size == 0x4 and event.Type == 0x1: - return True - -class PSDispScanner(scan.DiscontigScanner): - """ This scanner carves things that look like _EPROCESS structures. - - Since the _EPROCESS does not need to be linked to the process - list, this scanner is useful to recover terminated or cloaked - processes. - """ - checks = [ ("DispatchHeaderCheck", {}), - ("CheckDTBAligned", {}), - ("CheckThreadList", {}), - ("CheckSynchronization", {}) - ] - -class PSDispScan(commands.command, cache.Testable): - """ Scan Physical memory for _EPROCESS objects based on their Dispatch Headers""" - - # Declare meta information associated with this plugin - - meta_info = dict( - author = 'Brendan Dolan-Gavitt', - copyright = 'Copyright (c) 2007,2008 Brendan Dolan-Gavitt', - contact = 'bdolangavitt@wesleyan.edu', - license = 'GNU General Public License 2.0 or later', - url = 'http://moyix.blogspot.com/', - os = 'WIN_32_XP_SP2', - version = '1.0', - ) - - @cache.CacheDecorator("tests/psscan") - def calculate(self): - address_space = utils.load_as(self._config, astype = 'physical') - - for offset in PSDispScanner().scan(address_space): - yield obj.Object('_EPROCESS', vm = address_space, offset = offset) - - def render_dot(self, outfd, data): - objects = set() - links = set() - - for eprocess in data: - label = "{0} | {1} |".format(eprocess.UniqueProcessId, - eprocess.ImageFileName) - if eprocess.ExitTime: - label += "exited\\n{0}".format(eprocess.ExitTime) - options = ' style = "filled" fillcolor = "lightgray" ' - else: - label += "running" - options = '' - - objects.add('pid{0} [label="{1}" shape="record" {2}];\n'.format(eprocess.UniqueProcessId, - label, options)) - links.add("pid{0} -> pid{1} [];\n".format(eprocess.InheritedFromUniqueProcessId, - eprocess.UniqueProcessId)) - - ## Now write the dot file - outfd.write("digraph processtree { \ngraph [rankdir = \"TB\"];\n") - for link in links: - outfd.write(link) - - for item in objects: - outfd.write(item) - outfd.write("}") - - def render_text(self, outfd, data): - ## Just grab the AS and scan it using our scanner - outfd.write(" Offset Name PID PPID PDB Time created Time exited \n" + \ - "---------- ---------------- ------ ------ ---------- ------------------------ ------------------------ \n") - - for eprocess in data: - outfd.write("{0:#010x} {1:16} {2:6} {3:6} {4:#010x} {5:24} {6:24}\n".format( - eprocess.obj_offset, - eprocess.ImageFileName, - eprocess.UniqueProcessId, - eprocess.InheritedFromUniqueProcessId, - eprocess.Pcb.DirectoryTableBase, - eprocess.CreateTime or '', - eprocess.ExitTime or '')) diff --git a/contrib/plugins/scanprof.py b/contrib/plugins/scanprof.py deleted file mode 100644 index 37a37e9a8..000000000 --- a/contrib/plugins/scanprof.py +++ /dev/null @@ -1,57 +0,0 @@ -# Volatility -# -# Authors: -# Mike Auty -# -# 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 -# - -import sys -import itertools -import timeit - -class ScanProfInstance(object): - def __init__(self, func, *args): - self.func = func - self.args = args - self.results = [] - - def __call__(self): - self.results = self.func(*self.args) - -def permscan(self, address_space, offset = 0, maxlen = None): - times = [] - # Run a warm-up scan to ensure the file is cached as much as possible - self.oldscan(address_space, offset, maxlen) - - perms = list(itertools.permutations(self.checks)) - for i in range(len(perms)): - self.checks = perms[i] - print "Running scan {0}/{1}...".format(i + 1, len(perms)) - profobj = ScanProfInstance(self.oldscan, address_space, offset, maxlen) - value = timeit.timeit(profobj, number = self.repeats) - times.append((value, len(list(profobj.results)), i)) - - print "Scan results" - print "{0:20} | {1:7} | {2:6} | {3}".format("Time", "Results", "Perm #", "Ordering") - for val, l, ordering in sorted(times): - print "{0:20} | {1:7} | {2:6} | {3}".format(val, l, ordering, perms[ordering]) - sys.exit(1) - -def ScanProfiler(cls, repeats = 3): - cls.repeats = repeats - cls.oldscan = cls.scan - cls.scan = permscan - return cls diff --git a/contrib/plugins/verinfo.py b/contrib/plugins/verinfo.py deleted file mode 100644 index e10ef8878..000000000 --- a/contrib/plugins/verinfo.py +++ /dev/null @@ -1,403 +0,0 @@ -# Volatility -# -# Authors: -# Mike Auty -# -# 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 -# - -import re -import sre_constants -import struct -import volatility.plugins.procdump as procdump -import volatility.win32 as win32 -import volatility.obj as obj -import volatility.utils as utils -import volatility.addrspace as addrspace -import volatility.debug as debug - -MAX_STRING_BYTES = 260 - -ver_types = { -'_IMAGE_RESOURCE_DIRECTORY' : [ 0x12, { - 'Characteristics' : [ 0x0, ['unsigned long']], - 'Timestamp' : [ 0x4, ['unsigned long']], - 'MajorVersion': [ 0x8, ['unsigned short']], - 'Minorversion': [ 0xa, ['unsigned short']], - 'NamedEntriesCount': [ 0xc, ['unsigned short']], - 'IdEntriesCount': [0xe, ['unsigned short']], - 'Entries': [0x10, ['array', lambda x: x.NamedEntriesCount + x.IdEntriesCount, ['_IMAGE_RESOURCE_DIRECTORY_ENTRY']]], -} ], -'_IMAGE_RESOURCE_DIRECTORY_ENTRY': [0x8, { - 'Name' : [ 0x0, ['unsigned long']], - 'DataOffset' : [ 0x4, ['unsigned long']], -} ], -'_IMAGE_RESOURCE_DATA_ENTRY' : [0x10, { - 'DataOffset' : [0x0, ['unsigned long']], - 'Size' : [0x4, ['unsigned long']], - 'CodePage' : [0x8, ['unsigned long']], - 'Reserved' : [0xc, ['unsigned long']], -} ], -'_IMAGE_RESOURCE_DIR_STRING_U' : [0x4, { - 'Length': [0x0, ['unsigned short']], - 'Value' : [0x2, ['array', lambda x: x.Length, ['unsigned short']]], -} ], -'_VS_VERSION_INFO' : [0x26, { - 'Length': [0x0, ['unsigned short']], - 'ValueLength': [0x2, ['unsigned short']], - 'Type': [0x4, ['unsigned short']], - 'Key': [0x6, ['array', len("VS_VERSION_INFO "), ['unsigned short']]], - 'FileInfo': [lambda x: (((x.Key.obj_offset + x.Key.size() + 3) / 4) * 4), ['_VS_FIXEDFILEINFO']], -} ], -'VerStruct' : [0x26, { - 'Length': [0x0, ['unsigned short']], - 'ValueLength': [0x2, ['unsigned short']], - 'Type': [0x4, ['unsigned short']], - 'Key': [0x6, ['array', MAX_STRING_BYTES, ['unsigned short']]], -} ], -'_VS_FIXEDFILEINFO': [0x34, { - 'Signature': [0x0, ['unsigned long']], - 'StructVer': [0x4, ['unsigned long']], - 'FileVerMS': [0x8, ['unsigned long']], - 'FileVerLS': [0xC, ['unsigned long']], - 'ProdVerMS': [0x10, ['unsigned long']], - 'ProdVerLS': [0x14, ['unsigned long']], - 'FileFlagsMask': [0x18, ['unsigned long']], - 'FileFlags': [0x1C, ['unsigned long']], - 'FileOS': [0x20, ['Enumeration', {'choices': { - 0x0: 'Unknown', - 0x10000: 'DOS', - 0x20000: 'OS/2 16-bit', - 0x30000: 'OS/2 32-bit', - 0x40000: 'Windows NT', - 0x1: 'Windows 16-bit', - 0x2: 'Presentation Manager 16-bit', - 0x3: 'Presentation Manager 32-bit', - 0x4: 'Windows 32-bit', - 0x10001: 'Windows 16-bit running on DOS', - 0x10004: 'Windows 32-bit running on DOS', - 0x20002: 'Presentation Manager running on OS/2 (16-bit)', - 0x30003: 'Presentation Manager running on OS/2 (32-bit)', - 0x40004: 'Windows NT', - }} ]], - 'FileType': [0x24, ['Enumeration', {'choices': { - 0x0: 'Unknown', - 0x1: 'Application', - 0x2: 'Dynamic Link Library', - 0x3: 'Driver', - 0x4: 'Font', - 0x5: 'Virtual Device', - 0x7: 'Static Library', - }} ]], - 'FileSubType': [0x28, ['unsigned long']], - 'FileDate': [0x2C, ['WinTimeStamp']], -} ], -} - -class VerStruct(obj.Struct): - """Generic Version Structure""" - - def _determine_key(self, findend = False): - """Determines the string value for or end location of the key""" - if self.Key != None: - name = None - for n in self.Key: - if n == None: - return n - # If the letter's valid, then deal with it - if n == 0: - if findend: - return n.obj_offset + n.size() - name = self.obj_vm.read(self.Key.obj_offset, n.obj_offset - self.Key.obj_offset).decode("utf16", "ignore").encode("ascii", 'backslashreplace') - break - return name - return self.Key - - def get_key(self): - """Returns the VerStruct Name""" - return self._determine_key() - - def offset_pad(self, offset): - """Pads an offset to a 32-bit alignment""" - return (((offset + 3) / 4) * 4) - - def get_children(self): - """Returns the available children""" - offset = self.offset_pad(self._determine_key(True)) - if self.ValueLength > 0: - # Nasty hardcoding unicode (length*2) length in here, - # but what else can we do? - return self.obj_vm.read(offset, self.ValueLength * 2) - else: - return self._recurse_children(offset) - - def _recurse_children(self, offset): - """Recurses thorugh the available children""" - while offset < self.obj_offset + self.Length: - item = obj.Object("VerStruct", offset = offset, vm = self.obj_vm, parent = self) - if item.Length < 1 or item.get_key() == None: - raise StopIteration("Could not recover a key for a child at offset {0}".format(item.obj_offset)) - yield item.get_key(), item.get_children() - offset = self.offset_pad(offset + item.Length) - raise StopIteration("No children") - -class _VS_VERSION_INFO(VerStruct): - """Version Information""" - - def get_children(self): - """Recurses through the children of a Version Info records""" - offset = self.offset_pad(self.FileInfo.obj_offset + self.ValueLength) - return self._recurse_children(offset) - -class _VS_FIXEDFILEINFO(obj.Struct): - """Fixed (language and codepage independent) information""" - - def file_version(self): - """Returns the file version""" - return self.get_version(self.FileVerMS) + "." + self.get_version(self.FileVerLS) - - def product_version(self): - """Returns the product version""" - return self.get_version(self.ProdVerMS) + "." + self.get_version(self.ProdVerLS) - - def get_version(self, value): - """Returns a version in four parts""" - version = [] - for i in range(2): - version = [(value >> (i * 16)) & 0xFFFF] + version - return '.'.join([str(x) for x in version]) - - def file_type(self): - """Returns the type of the file""" - ftype = str(self.FileType) - choices = None - if self.FileType == 'Driver': - choices = { - 0x0: 'Unknown', - 0x1: 'Printer', - 0x2: 'Keyboard', - 0x3: 'Language', - 0x4: 'Display', - 0x5: 'Mouse', - 0x6: 'Network', - 0x7: 'System', - 0x8: 'Installable', - 0x9: 'Sound', - 0xA: 'Comms', - 0xB: 'Input Method', - 0xC: 'Versioned Printer', - } - elif self.FileType == 'Font': - choices = { - 0x1: 'Raster', - 0x2: 'Vector', - 0x3: 'Truetype', - } - if choices != None: - subtype = obj.Object('Enumeration', 0x28, vm = self.obj_vm, parent = self, choices = choices) - ftype += " (" + str(subtype) + ")" - - return ftype - - def flags(self): - """Returns the file's flags""" - data = struct.pack('=I', self.FileFlags & self.FileFlagsMask) - addr_space = addrspace.BufferAddressSpace(self.obj_vm.get_config(), 0, data) - bitmap = {'Debug': 0, - 'Prerelease': 1, - 'Patched': 2, - 'Private Build': 3, - 'Info Inferred': 4, - 'Special Build' : 5, - } - return obj.Object('Flags', offset = 0, vm = addr_space, bitmap = bitmap) - - def v(self): - """Returns the value of the structure""" - val = ("File version : {0}\n" + - "Product version : {1}\n" + - "Flags : {2}\n" + - "OS : {3}\n" + - "File Type : {4}\n" + - "File Date : {5}").format(self.file_version(), self.product_version(), - self.flags(), self.FileOS, self.file_type(), self.FileDate or '') - return val - -class _IMAGE_RESOURCE_DIR_STRING_U(obj.Struct): - """Handles Unicode-esque strings in IMAGE_RESOURCE_DIRECTORY structures""" - # This is very similar to a UNICODE object, perhaps they should be merged somehow? - def v(self): - """Value function for _IMAGE_RESOURCE_DIR_STRING_U""" - try: - length = self.Length.v() - if length > 1024: - length = 0 - data = self.obj_vm.read(self.Value.obj_offset, length) - return data.decode("utf16", "ignore").encode("ascii", 'backslashreplace') - except Exception, _e: - return '' - -class _IMAGE_RESOURCE_DIRECTORY(obj.Struct): - """Handles Directory Entries""" - def __init__(self, theType = None, offset = None, vm = None, parent = None, *args, **kwargs): - self.sectoffset = offset - obj.Struct.__init__(self, theType = theType, offset = offset, vm = vm, parent = parent, *args, **kwargs) - - def get_entries(self): - """Gets a tree of the entries from the top level IRD""" - for irde in self.Entries: - if irde != None: - if irde.Name & 0x80000000: - # Points to a Name object - name = obj.Object("_IMAGE_RESOURCE_DIR_STRING_U", (irde.Name & 0x7FFFFFFF) + self.sectoffset, vm = self.obj_vm, parent = irde) - else: - name = int(irde.Name) - if irde.DataOffset & 0x80000000: - # We're another DIRECTORY - retobj = obj.Object("_IMAGE_RESOURCE_DIRECTORY", (irde.DataOffset & 0x7FFFFFFF) + self.sectoffset, vm = self.obj_vm, parent = irde) - retobj.sectoffset = self.sectoffset - else: - # We're a DATA_ENTRY - retobj = obj.Object("_IMAGE_RESOURCE_DATA_ENTRY", irde.DataOffset + self.sectoffset, vm = self.obj_vm, parent = irde) - yield (name, bool(irde.DataOffset & 0x80000000), retobj) - -resource_types = { - 'RT_CURSOR' : 1, - 'RT_BITMAP' : 2, - 'RT_ICON' : 3, - 'RT_MENU' : 4, - 'RT_DIALOG' : 5, - 'RT_STRING' : 6, - 'RT_FONTDIR' : 7, - 'RT_FONT' : 8, - 'RT_ACCELERATOR' : 9, - 'RT_RCDATA' : 10, - 'RT_MESSAGETABLE' : 11, - 'RT_GROUP_CURSOR' : 12, - 'RT_GROUP_ICON' : 14, - 'RT_VERSION' : 16, - 'RT_DLGINCLUDE' : 17, - 'RT_PLUGPLAY' : 19, - 'RT_VXD' : 20, - 'RT_ANICURSOR' : 21, - 'RT_ANIICON' : 22, - 'RT_HTML' : 23, -} - -class VerInfo(procdump.ProcExeDump): - """Prints out the version information from PE images""" - - def __init__(self, config, *args): - procdump.ProcExeDump.__init__(self, config, *args) - config.remove_option("OFFSET") - config.remove_option("PID") - config.add_option("OFFSET", short_option = "o", type = 'int', - help = "Offset of the module to print the version information for") - config.add_option('REGEX', short_option = "r", default = None, - help = 'Dump modules matching REGEX') - config.add_option('IGNORE-CASE', short_option = 'i', action = 'store_true', - help = 'ignore case in pattern match', default = False) - - def calculate(self): - """Returns a unique list of modules""" - addr_space = utils.load_as(self._config) - for cls in [_IMAGE_RESOURCE_DIRECTORY, _IMAGE_RESOURCE_DIR_STRING_U, _VS_FIXEDFILEINFO, _VS_VERSION_INFO, VerStruct]: - addr_space.profile.object_classes[cls.__name__] = cls - addr_space.profile.add_types(ver_types) - - if self._config.REGEX is not None: - try: - if self._config.IGNORE_CASE: - module_pattern = re.compile(self._config.REGEX, flags = sre_constants.SRE_FLAG_IGNORECASE) - else: - module_pattern = re.compile(self._config.REGEX) - except sre_constants.error, e: - debug.error('Regular expression parsing error: {0}'.format(e)) - - if self._config.OFFSET is not None: - if not addr_space.is_valid_address(self._config.OFFSET): - debug.error("Specified offset is not valid for the provided address space") - yield addr_space, self._config.OFFSET - raise StopIteration - - tasks = win32.tasks.pslist(addr_space) - - for task in tasks: - for m in task.get_load_modules(): - if self._config.REGEX is not None: - if not (module_pattern.search(str(m.FullDllName)) - or module_pattern.search(str(m.BaseDllName))): - continue - - yield task.get_process_address_space(), m - - def display_unicode(self, string): - """Renders a UTF16 string""" - if string is None: - return '' - return string.decode("utf16", "ignore").encode("ascii", 'backslashreplace') - - def get_version_info(self, addr_space, offset): - """Accepts an address space and an executable image offset - - Returns a VS_VERSION_INFO object of NoneObject - """ - if not addr_space.is_valid_address(offset): - return obj.NoneObject("Disk image not resident in memory") - - try: - nt_header = self.get_nt_header(addr_space = addr_space, - base_addr = offset) - except ValueError: - return obj.NoneObject("PE file failed initial sanity checks") - - # header = s.read(m.DllBase, nt_header.OptionalHeader.SizeOfHeaders) - - for sect in nt_header.get_sections(self._config.UNSAFE): - if str(sect.Name) == '.rsrc': - root = obj.Object("_IMAGE_RESOURCE_DIRECTORY", offset + sect.VirtualAddress, addr_space) - for rname, rentry, rdata in root.get_entries(): - # We're a VERSION resource and we have subelements - if rname == resource_types['RT_VERSION'] and rentry: - for sname, sentry, sdata in rdata.get_entries(): - # We're the single sub element of the VERSION - if sname == 1 and sentry: - # Get the string tables - for _stname, stentry, stdata in sdata.get_entries(): - if not stentry: - return obj.Object("_VS_VERSION_INFO", offset = (stdata.DataOffset + offset), vm = addr_space) - - def render_text(self, outfd, data): - """Renders the text""" - for s, m in data: - outfd.write(str(m.FullDllName)) - outfd.write("\n") - vinfo = self.get_version_info(s, m.DllBase) - if vinfo != None: - outfd.write(" File version : {0}\n".format(vinfo.FileInfo.file_version())) - outfd.write(" Product version : {0}\n".format(vinfo.FileInfo.product_version())) - outfd.write(" Flags : {0}\n".format(vinfo.FileInfo.flags())) - outfd.write(" OS : {0}\n".format(vinfo.FileInfo.FileOS)) - outfd.write(" File Type : {0}\n".format(vinfo.FileInfo.file_type())) - outfd.write(" File Date : {0}\n".format(vinfo.FileInfo.FileDate or '')) - for name, children in vinfo.get_children(): - if name == 'StringFileInfo': - for _codepage, strings in children: - for string, value in strings: - # Make sure value isn't a generator, and we've a subtree to deal with - if isinstance(value, type(strings)): - outfd.write(" {0} : Subtrees not yet implemented\n".format(string)) - else: - outfd.write(" {0} : {1}\n".format(string, self.display_unicode(value))) diff --git a/contrib/pyxpress/README b/contrib/pyxpress/README index fa797588a..154f5ec57 100644 --- a/contrib/pyxpress/README +++ b/contrib/pyxpress/README @@ -1,5 +1,5 @@ This module implements the xpress decompression algorithm in c. This algorithm -is used in hibernation files among other things. Volatility is shipped with a +is used in hibernation files among other things. Rekall is shipped with a python only decompression algorithm, but this is very slow. By decompressing in C we can increase performance of hibernation file parsing. @@ -7,5 +7,5 @@ To install, simply run: python setup.py install -This will build the module and install on the system. Volatility will +This will build the module and install on the system. Rekall will automatically choose the fast decompressor if it is available. \ No newline at end of file diff --git a/contrib/pyxpress/pyxpress.c b/contrib/pyxpress/pyxpress.c index 84733aa47..de69524a6 100644 --- a/contrib/pyxpress/pyxpress.c +++ b/contrib/pyxpress/pyxpress.c @@ -5,6 +5,7 @@ Michael Cohen . SandMan framework. Copyright 2008 (c) Matthieu Suiche. +Copyright 2013 Google Inc. All Rights Reserved. This file is part of SandMan. diff --git a/contrib/pyxpress/setup.py b/contrib/pyxpress/setup.py index ee605e2d7..39ff6a29d 100644 --- a/contrib/pyxpress/setup.py +++ b/contrib/pyxpress/setup.py @@ -1,3 +1,11 @@ +# Rekall Memory Forensics +# +# Copyright 2013 Google Inc. All Rights Reserved. +# +# Authors: +# Copyright (C) 2012 Michael Cohen + + from distutils.core import setup, Extension pyxpress = Extension('pyxpress', diff --git a/docs/development.html b/docs/development.html index 2d83d6701..a4c718af5 100644 --- a/docs/development.html +++ b/docs/development.html @@ -3,8 +3,8 @@ - -Volatility Technology Preview Developer information + +The Rekall Memory Forensic Framework