Commit 4cdfb39b authored by Sophie Brun's avatar Sophie Brun

Imported Upstream version 2.5

parent 2d542df3
*.py[cod]
# Pycharm ide library
.idea
*.swp
# C extensions
......
......@@ -4,7 +4,16 @@ This file identifies core Volatility authors.
All lists are alphabetical.
===============================================
Volatility 2.0, 2.1, 2.2, and 2.3:
Volatility 2.4, 2.5:
------------
Mike Auty
Andrew Case
Michael Hale Ligh
Jamie Levy
AAron Walters
Volatility 2.0, 2.1, 2.2, 2.3:
------------
Mike Auty
......
......@@ -14,19 +14,28 @@ intentional. Please bring it to our attention!
Volatility 2.5:
Adam Bridge for adding a --count option (humanly readable byte stats) to imagecopy/raw2dmp
Sebastien Bourdon-Richard for various patches and bug fixes
Bruno Constanzo for various patches to enhance performance/optimization
Glenn P. Edwards, Jr for adding combined user/kernel scans, --case, and ascii/unicode options to yarascan
@f-s-p for converting some plugins to unfied output format
Cem Gurkok for submitting the mac_threads plugin
Takahiro Haruyama for noticing and fixing a bug in impscan
@masdif for contributing a fix for kernel 3.7+ in linux/module.c
Wyatt Roersma for converting a large number of plugins to the unified output format
Karl Vogel for pointing out an issue with IPv4 addresses on big endian systems
Volatility 2.4:
Justin Capella and Espen Olsen for their work on the Qemu ELF core dumps
Steven Adair for assistance identifying a large memory PAE bug
Sebastien Bourdon-Richard for his work on the VMware vmem/vmss split (with meta) AS
Justin Capella and Espen Olsen for their work on the Qemu ELF core dumps
Cem Gurkok for help updating Mac OS X support for 10.9
Matt McCormack for supplying a patch to rebase dumped PE files
Stewart McIntyre for extending apihooks for detecting JMP FAR instructions
Matt McCormack for supplying a patch to rebase dumped PE files
Kevin Marker for contributing over 160 standard build Linux profiles
Steven Adair for assistance identifying a large memory PAE bug
Cem Gurkok for help updating Mac OS X support for 10.9
synack33 for creating various Mac OS X profiles, including initial ones for 10.10
Raphaël Vinot for his patch to fix IPython within volshell
synack33 for creating various Mac OS X profiles, including initial ones for 10.10
Volatility 2.3:
......
This diff is collapsed.
# Volatility
# Copyright (c) 2015 Michael Ligh (michael.ligh@mnin.org)
#
# This file is part of Volatility.
#
# Volatility 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,
# 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 Volatility. If not, see <http://www.gnu.org/licenses/>.
#
import copy, StringIO, json
import volatility.conf as conf
import volatility.registry as registry
import volatility.commands as commands
import volatility.addrspace as addrspace
registry.PluginImporter()
def get_json(config, plugin_class):
strio = StringIO.StringIO()
plugin = plugin_class(copy.deepcopy(config))
plugin.render_json(strio, plugin.calculate())
return json.loads(strio.getvalue())
def get_config(profile, target_path):
config = conf.ConfObject()
registry.register_global_options(config, commands.Command)
registry.register_global_options(config, addrspace.BaseAddressSpace)
config.parse_options()
config.PROFILE = profile
config.LOCATION = "file://{0}".format(target_path)
return config
\ No newline at end of file
# Volatility
# Copyright (c) 2015 Michael Ligh (michael.ligh@mnin.org)
#
# This file is part of Volatility.
#
# Volatility 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,
# 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 Volatility. If not, see <http://www.gnu.org/licenses/>.
#
import sys
import volatility.plugins.taskmods as taskmods
import libapi
def main():
## sys.argv[1] = volatility profile
## sys.argv[2] = full path on disk to your memory sample
config = libapi.get_config(sys.argv[1], sys.argv[2])
data = libapi.get_json(config, taskmods.PSList)
## `data` now contains json with two keys: `columns` and `rows`, where `columns`
## contains a list of column headings (matching the corresponding volatility
## plugin output) and `rows` contains a list of the values for each object found.
## you can either print/save all columns, or you can drill down to a particular
## column by getting the desired column's index as shown below and then accessing
## the index in each row. the following example prints each process' name.
name_index = data['columns'].index('Name')
for row in data['rows']:
print row[name_index]
if __name__ == "__main__":
main()
\ No newline at end of file
# Openpyxl hook
#
# This currently contains the hardcoded location for the .constants.json file
# It could be improved by carrying out a search, or using sys.path
#
# This also requires the openpyxl module to be modified with the following patch:
# import sys
# if hasattr(sys, '_MEIPASS'):
# here = sys._MEIPASS
import os
import sys
datas = []
for path in sys.path:
datas.append((os.path.join(path, "openpyxl", ".constants.json"), ""))
import os
import sys
datas = []
for path in sys.path:
datas.append(("yara.pyd", ""))
datas.append(("yara.so", ""))
\ No newline at end of file
......@@ -51,7 +51,7 @@ opts = {}
opts['name'] = "volatility"
opts['version'] = volatility.constants.VERSION
opts['description'] = "Volatility -- Volatile memory framwork"
opts['description'] = "Volatility -- Volatile memory framework"
opts['author'] = "AAron Walters"
opts['author_email'] = "awalters@4tphi.net"
opts['url'] = "http://www.volatilityfoundation.org"
......@@ -59,6 +59,7 @@ opts['license'] = "GPL"
opts['scripts'] = ["vol.py"]
opts['packages'] = ["volatility",
"volatility.win32",
"volatility.renderers",
"volatility.plugins",
"volatility.plugins.addrspaces",
"volatility.plugins.overlays",
......
obj-m += module.o
KDIR ?= /lib/modules/3.5.0-23-generic/build
-include version.mk
all: dwarf
dwarf: module.c
$(MAKE) -C $(KDIR) CONFIG_DEBUG_INFO=y M="$(PWD)" modules
dwarfdump -di module.ko > module.dwarf
$(MAKE) -C $(KDIR) M="$(PWD)" clean
clean:
$(MAKE) -C $(KDIR) M="$(PWD)" clean
rm -f module.dwarf
......@@ -15,8 +15,8 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _ELF_H
#define _ELF_H 1
......
......@@ -175,7 +175,7 @@ struct rt_hash_bucket {
struct rtable __rcu *chain;
} rt_hash_bucket;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)
#ifndef RADIX_TREE_MAX_TAGS
#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6)
#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
#define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1)
......@@ -192,6 +192,14 @@ struct radix_tree_node {
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
#define OUR_OWN_MOD_STRUCTS
#endif
#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
#define OUR_OWN_MOD_STRUCTS
#endif
#ifdef OUR_OWN_MOD_STRUCTS
struct module_sect_attr
{
struct module_attribute mattr;
......@@ -404,6 +412,11 @@ struct slab slab;
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
/* Starting with Linux kernel 3.7 the struct timekeeper is defined in include/linux/timekeeper_internal.h */
#include <linux/timekeeper_internal.h>
#else
/* Before Linux kernel 3.7 the struct timekeeper has to be taken from kernel/time/timekeeping.c */
typedef u64 cycle_t;
......@@ -465,6 +478,7 @@ struct timekeeper {
seqlock_t lock;
};
#endif
struct timekeeper my_timekeeper;
......
# Volatility
#
# This file is part of Volatility.
#
# Volatility 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,
# 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 Volatility. If not, see <http://www.gnu.org/licenses/>.
#
'''
This helper script generates (kernel version, version address pairs)
to help generate the list used by mac_get_profiles
Run it from the Mac directory of the Volatility profiles repo
'''
import os, sys, re
import zipfile
def parse_dsymutil(data, module):
"""Parse the symbol file."""
sys_map = {}
sys_map[module] = {}
want_lower = ["_IdlePML4"]
type_map = {}
type_map[module] = {}
# get the system map
for line in data.splitlines():
ents = line.split()
match = re.search("\[.*?\(([^\)]+)\)\s+[0-9A-Fa-z]+\s+\d+\s+([0-9A-Fa-f]+)\s'(\w+)'", line)
if match:
(sym_type, addr, name) = match.groups()
sym_type = sym_type.strip()
addr = int(addr, 16)
if addr == 0 or name == "":
continue
if not name in sys_map[module]:
sys_map[module][name] = [(addr, sym_type)]
# every symbol is in the symbol table twice
# except for the entries in 'want_lower', we need the higher address for all
oldaddr = sys_map[module][name][0][0]
if addr < oldaddr and name in want_lower:
sys_map[module][name] = [(addr, sym_type)]
if not addr in type_map[module]:
type_map[module][addr] = (name, [sym_type])
type_map[module][addr][1].append(sym_type)
return sys_map["kernel"]
print "profiles = ["
for path in set("."):
for path, _, files in os.walk(path):
for fn in files:
if zipfile.is_zipfile(os.path.join(path, fn)):
profpkg = zipfile.ZipFile(os.path.join(path, fn))
for f in profpkg.filelist:
if 'symbol.dsymutil' in f.filename.lower():
data = parse_dsymutil(profpkg.read(f.filename), "kernel")
if "_lowGlo" in data:
lg = data["_lowGlo"][0][0]
else:
lg = "0"
if "_BootPML4" in data:
aslr = 1
else:
aslr = 0
name = fn.replace(".zip", "")
name = 'Mac' + name.replace('.', '_')
if name.find("Intel") == -1:
name = name + "x64"
else:
name = name + "x86"
print "[\"%s\", %s, %s, %d]," % (name, data["_version"][0][0], lg, aslr)
print "]"
import json
import sys
import os
"""
Author: Gleeda <jamie.levy@gmail.com>
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.
parsesummary.py [summary_file]
Parses summary files created from the dumpfiles plugin
"""
def usage(name):
print "{0} [summary_file]".format(name)
def main():
try:
summary = sys.argv[1]
if os.path.isfile(summary):
f = open(summary, "r")
else:
print summary, "is not a file!"
usage(sys.argv[0])
return
except:
usage(sys.argv[0])
return
heading = "*" * 80
for line in f.readlines():
print heading
item = json.loads(line.strip())
print "File: {0} -> {1}".format(item["name"], item["ofpath"])
print "\tPID: {0}".format(item["pid"])
print "\t_FILE_OBJECT offset: 0x{0:x}".format(item["fobj"])
print "\tType: {0}".format(item["type"])
vacbary = item.get("vacbary", [])
if item["type"] == "SharedCacheMap" and vacbary != []:
for vacb in vacbary:
print "\tSize: {0}".format(vacb["size"])
present = vacb.get("present", None)
padding = vacb.get("pad", None)
if present != None:
print "\tPresent Pages:"
for page in present:
print "\t\tOffset(V): 0x{0:x}, Length: {1}".format(page[0], page[1])
else:
present = item.get("present", None)
if present != None:
print "\tPresent Pages:"
if item["type"] != "SharedCacheMap":
for page in present:
print "\t\tOffset(P) 0x{0:x} FileOffset: 0x{1:x}, Size: {2}".format(page[0], page[1], page[2])
padding = item.get("pad", None)
if padding != None:
print "\tPadding:"
for pad in padding:
print "\t\tFileOffset: 0x{0:x} x 0x{1:x}".format(pad[0], pad[1])
print heading
if __name__ == "__main__":
main()
......@@ -77,7 +77,7 @@ class BaseAddressSpace(object):
## By default load the profile that the user asked for
config.add_option("PROFILE", default = "WinXPSP2x86", type = 'str',
nargs = 1, action = "callback", callback = check_valid_profile,
help = "Name of the profile to load")
help = "Name of the profile to load (use --info to see a list of supported profiles)")
config.add_option("LOCATION", default = None, short_option = 'l',
help = "A URN location from which to load an address space")
......
# Volatility
# Copyright (C) 2008-2013 Volatility Foundation
# Copyright (C) 2008-2015 Volatility Foundation
#
# This file is part of Volatility.
#
......@@ -17,12 +17,22 @@
# along with Volatility. If not, see <http://www.gnu.org/licenses/>.
#
import sys, textwrap
import os
import sys
import textwrap
import volatility.debug as debug
import volatility.fmtspec as fmtspec
import volatility.obj as obj
import volatility.registry as registry
import volatility.renderers as renderers
import volatility.addrspace as addrspace
from volatility.renderers.basic import Address, Address64, Hex, Bytes
from volatility.renderers.dot import DotRenderer
from volatility.renderers.html import HTMLRenderer, JSONRenderer
from volatility.renderers.sqlite import SqliteRenderer
from volatility.renderers.text import TextRenderer, FormatCellRenderer, GrepTextRenderer
from volatility.renderers.xlsx import XLSXRenderer
class Command(object):
""" Base class for each plugin command """
......@@ -35,10 +45,11 @@ class Command(object):
# Make these class variables so they can be modified across every plugin
elide_data = True
tablesep = " "
text_sort_column = None
def __init__(self, config, *_args, **_kwargs):
""" Constructor uses args as an initializer. It creates an instance
of OptionParser, populates the options, and finally parses the
of OptionParser, populates the options, and finally parses the
command line. Options are stored in the self.opts attribute.
"""
self._config = config
......@@ -49,11 +60,11 @@ class Command(object):
"""Registers options into a config object provided"""
config.add_option("OUTPUT", default = 'text',
cache_invalidator = False,
help = "Output in this format (format support is module specific)")
help = "Output in this format (support is module specific, see the Module Output Options below)")
config.add_option("OUTPUT-FILE", default = None,
cache_invalidator = False,
help = "write output in this file")
help = "Write output in this file")
config.add_option("VERBOSE", default = 0, action = 'count',
cache_invalidator = False,
......@@ -88,16 +99,21 @@ class Command(object):
""" Executes the plugin command."""
# Check we can support the plugins
profs = registry.get_plugin_classes(obj.Profile)
# force user to give a profile if a plugin
# force user to give a profile if a plugin
# other than kdbgscan or imageinfo are given:
if self.__class__.__name__.lower() in ["kdbgscan", "imageinfo"] and self._config.PROFILE == None:
self._config.update("PROFILE", "WinXPSP2x86")
elif self._config.PROFILE == None:
debug.error("You must set a profile!")
if self._config.PROFILE not in profs:
debug.error("Invalid profile " + self._config.PROFILE + " selected")
if not self.is_valid_profile(profs[self._config.PROFILE]()):
debug.error("This command does not support the profile " + self._config.PROFILE)
plugin_name = self.__class__.__name__.lower()
if plugin_name != "mac_get_profile":
if self._config.PROFILE == None:
if plugin_name in ["kdbgscan", "imageinfo"]:
self._config.update("PROFILE", "WinXPSP2x86")
else:
debug.error("You must set a profile!")
if self._config.PROFILE not in profs:
debug.error("Invalid profile " + self._config.PROFILE + " selected")
if not self.is_valid_profile(profs[self._config.PROFILE]()):
debug.error("This command does not support the profile " + self._config.PROFILE)
# # Executing plugins is done in two stages - first we calculate
data = self.calculate()
......@@ -105,9 +121,11 @@ class Command(object):
## Then we render the result in some way based on the
## requested output mode:
function_name = "render_{0}".format(self._config.OUTPUT)
if self._config.OUTPUT_FILE:
outfd = open(self._config.OUTPUT_FILE, 'w')
# TODO: We should probably check that this won't blat over an existing file
if not self._config.OUTPUT == "sqlite" and self._config.OUTPUT_FILE:
if os.path.exists(self._config.OUTPUT_FILE):
debug.error("File " + self._config.OUTPUT_FILE + " already exists. Cowardly refusing to overwrite it...")
outfd = open(self._config.OUTPUT_FILE, 'wb')
# TODO: We should probably check that this won't blat over an existing file
else:
outfd = sys.stdout
......@@ -217,3 +235,94 @@ class Command(object):
result = self._elide(("{0:" + spec.to_string() + "}").format(args[index]), spec.minwidth)
reslist.append(result)
outfd.write(self.tablesep.join(reslist) + "\n")
text_stock_renderers = {Hex: "#x",
Address: "#8x",
Address64: "#16x",
int: "",
str: "<",
float: ".2",
Bytes: ""}
def text_cell_renderers(self, columns):
"""Returns default renderers for the columns listed"""
renderlist = [FormatCellRenderer("")] * len(columns)
# FIXME: Really, this should be handled by the plugin knowing what type of AS each object comes from
# However, as a nasty workaround, we can force all x64 profiles to produce addresses that are 64-bit in length
# It does not deal with PAE address spaces, or WoW64 addresses, or anything else weird or wonderful
# This will NOT be in volatility 3.0
x64 = False
if self._config.PROFILE.endswith("x64"):
x64 = True
for column in columns:
if not isinstance(column, renderers.Column):
raise TypeError("Columns must be a list of Column objects")
columntype = column.type if not x64 or column.type != Address else Address64
renderlist[column.index] = FormatCellRenderer(self.text_stock_renderers[columntype])
return renderlist
def unified_output(self, data):
raise NotImplementedError("Rendering using the unified output format has not been implemented for this plugin.")
def _render(self, outfd, renderer, data):
output = self.unified_output(data)
if isinstance(output, renderers.TreeGrid):
renderer.render(outfd, output)
else:
raise TypeError("Unified Output must return a TreeGrid object")
def render_text(self, outfd, data):
self._render(outfd, TextRenderer(self.text_cell_renderers, sort_column = self.text_sort_column,
config = self._config), data)
def render_greptext(self, outfd, data):
try:
self._render(outfd, GrepTextRenderer(self.text_cell_renderers, sort_column = self.text_sort_column), data)
except NotImplementedError, why:
debug.error(why)
except TypeError, why:
debug.error(why)
def render_json(self, outfd, data):
try:
self._render(outfd, JSONRenderer(), data)
except NotImplementedError, why: