{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "_Volatility memory analysis notebook by Eric Hutchins_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[__The Volatility Framework__](https://code.google.com/p/volatility/) is a powerful and flexible library to analyze volatile memory (e.g., memory dumps). The primary way analysts use this framework is to run the `vol.py` script from the terminal with various plugins and parameters, printing the results of the command to stdout. \n", "\n", " $ python vol.py -f ds_fuzz_hidden_proc.img --profile=WinXPSP2x86 psscan\n", " \n", " Offset(P) Name PID PPID PDB Time created Time exited \n", " ---------- ---------------- ------ ------ ---------- -------------------- --------------------\n", " 0x0181b748 alg.exe 992 660 0x08140260 2008-11-15 23:43:25 \n", " 0x01843b28 wuauclt.exe 1372 1064 0x08140180 2008-11-26 07:39:38 \n", " \n", "This is a quintessential use-case for IPython Notebook: a place to document various commands, the result of those commands, and markup description to explain the methodology and significance. In other words: your full analysis! Furthermore, as we show at the end, rich inline images also make IPy a fantastic way to guide and document memory analysis.\n", "\n", "The downside is that the developers admit using the tools as a library is [not perfect](https://code.google.com/p/volatility/wiki/BasicUsage21#Using_Volatility_as_a_Library). Prepare to have to read some code. \n", "\n", "> Although its possible to use Volatility as a library, we hope to support it better in the future\n", "\n", "It is, however, very exciting to see this on the [roadmap](https://code.google.com/p/volatility/wiki/VolatilityRoadmap):\n", "\n", "> Interactive IPython shell" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Notebook Prerequisites__\n", "\n", "_Modules_\n", "\n", "* [Volatility Framework](https://code.google.com/p/volatility/)\n", "* [Pandas](http://pandas.pydata.org/)\n", "* [Hierarchymagic](https://github.com/tkf/ipython-hierarchymagic)\n", " - Requires [Graphviz](http://www.graphviz.org/)\n", "\n", "_Data_\n", "\n", "* [ds_fuzz_hidden_proc.img](http://amnesia.gtisc.gatech.edu/~moyix/ds_fuzz_hidden_proc.img.bz2) -- Sample memory image via [Sample Memory Images](https://code.google.com/p/volatility/wiki/SampleMemoryImages) directory. (Note: you'll have to bunzip the file before using)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from cStringIO import StringIO" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "# Imports following example from\n", "# https://code.google.com/p/volatility/wiki/BasicUsage21#Using_Volatility_as_a_Library\n", "import volatility.conf as conf\n", "import volatility.registry as registry\n", "import volatility.commands as commands\n", "import volatility.addrspace as addrspace\n", "\n", "import volatility.utils as utils\n", "import volatility.win32.network as network\n", "\n", "import volatility.plugins.taskmods as taskmods\n", "import volatility.plugins.vadinfo as vadinfo\n", "\n", "registry.PluginImporter()\n", "config = conf.ConfObject()\n", "\n", "registry.register_global_options(config, commands.Command)\n", "registry.register_global_options(config, addrspace.BaseAddressSpace)\n", "\n", "# You can print the cmds dictionary to see list of available plugins\n", "# These are the same commands you would specify to the command line vol.py script\n", "cmds = registry.get_plugin_classes(commands.Command, lower = True)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "# These parameters simulate the command line settings \"--profile\" and \"-f\" respectively\n", "config.PROFILE = \"WinXPSP2x86\"\n", "config.LOCATION = \"file:///c:/ds_fuzz_hidden_proc.img\"" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Iterate processes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The __PSScan__ module in The Volatility Framework scans physical memory for `EPROCESS` allocations. This method discovers processes that may be hidden/excluded from the normal process tree" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from volatility.plugins.filescan import PSScan\n", "import pandas as pd" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is the common way to invoke plugins. First, instantiate the plugin by passing the `config`. Each plugin should provide a `calculate` and `render_[something]` method. The most common renderer is `render_text`. Since Volatility is primarily intended to be run stand-alone from a terminal, it expects to write the output to a file buffer (or stdout). In our use-case, we want to direct this output into a buffer using the StringIO library.\n", "\n", "This approach should work for most Volatility plugins. You will have to check the code for each module to see how to populate additional `config` parameters as needed." ] }, { "cell_type": "code", "collapsed": false, "input": [ "ps = PSScan(config)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ "pstable = StringIO()\n", "psdata = ps.calculate()\n", "ps.render_text(pstable, psdata)\n", "print pstable.getvalue()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Offset(P) Name PID PPID PDB Time created Time exited \n", "---------- ---------------- ------ ------ ---------- -------------------- --------------------\n", "0x0181b748 alg.exe 992 660 0x08140260 2008-11-15 23:43:25 \n", "0x01843b28 wuauclt.exe 1372 1064 0x08140180 2008-11-26 07:39:38 \n", "0x0184e3a8 wscntfy.exe 560 1064 0x081402a0 2008-11-26 07:44:57 \n", "0x018557e0 alg.exe 512 672 0x08140260 2008-11-26 07:38:53 \n", "0x0185dda0 cmd.exe 940 1516 0x081401a0 2008-11-26 07:43:39 2008-11-26 07:45:49 \n", "0x018a13c0 VMwareService.e 1756 672 0x08140220 2008-11-26 07:38:45 \n", "0x018af448 VMwareUser.exe 1904 1516 0x08140100 2008-11-26 07:38:31 \n", "0x018af860 VMwareTray.exe 1896 1516 0x08140200 2008-11-26 07:38:31 \n", "0x018e75e8 spoolsv.exe 1648 672 0x081401e0 2008-11-26 07:38:28 \n", "0x019456e8 csrss.exe 592 360 0x08140040 2008-11-15 23:42:56 \n", "0x01946020 svchost.exe 828 660 0x081400c0 2008-11-15 23:42:57 \n", "0x019467e0 services.exe 660 616 0x08140080 2008-11-15 23:42:56 \n", "0x0194f658 svchost.exe 1016 660 0x08140100 2008-11-15 23:42:57 \n", "0x019533c8 svchost.exe 924 660 0x081400e0 2008-11-15 23:42:57 \n", "0x019ca478 explorer.exe 1516 1452 0x081401c0 2008-11-26 07:38:27 \n", "0x019dbc30 lsass.exe 684 620 0x081400a0 2008-11-26 07:38:15 \n", "0x019e4670 smss.exe 360 4 0x08140020 2008-11-26 07:38:11 \n", "0x019f7da0 svchost.exe 1164 672 0x08140140 2008-11-26 07:38:23 \n", "0x01a0e6f0 svchost.exe 1264 672 0x08140160 2008-11-26 07:38:25 \n", "0x01a1bd78 csrss.exe 596 360 0x08140040 2008-11-26 07:38:13 \n", "0x01a2b100 winlogon.exe 620 360 0x08140060 2008-11-26 07:38:14 \n", "0x01a3ba78 services.exe 672 620 0x08140080 2008-11-26 07:38:15 \n", "0x01a3d360 svchost.exe 932 672 0x081400e0 2008-11-26 07:38:18 \n", "0x01a59d70 svchost.exe 844 672 0x081400c0 2008-11-26 07:38:18 \n", "0x01aa2300 svchost.exe 1064 672 0x08140120 2008-11-26 07:38:20 \n", "0x01bcc830 System 4 0 0x00319000 \n", "\n" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "It would be nice to load the __PSScan__ output into a data structure for sorting/filtering/etc. We can loop through the task list ourselves and extract and normalize the key parameters into a dictionary. __Pandas__ can convert a list of dicts into a DataFrame trivially. And since our PSScan object is already in memory and Volatility has its own cache, traversing these objects again is very fast." ] }, { "cell_type": "code", "collapsed": false, "input": [ "taskinfo = []\n", "\n", "for task in ps.calculate():\n", " info = {}\n", " info['Name'] ='%s' % task.ImageFileName\n", " info['PID'] = '%i' % task.UniqueProcessId\n", " info['PPID'] = '%i' % task.InheritedFromUniqueProcessId\n", " info['Threads'] = '%s' % task.ActiveThreads\n", " info['HandleCount'] = '%s' % task.ObjectTable.HandleCount\n", " info['SessionID'] = '%s' % task.SessionId\n", " info['Wow64'] = '%s' % task.IsWow64\n", " info['Start'] = str(task.CreateTime or '')\n", " info['Exit'] = str(task.ExitTime or '')\n", " \n", " taskinfo.append(info)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stderr", "text": [ "No handlers could be found for logger \"volatility.obj\"\n" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convert the list of dict info into a DataFrame. First we specify column ordering (else it defaults to alphabetical). Second we set the index of the table to be the PID for each selection. Then for fun, we interpret the Start and Exit timestamps as actual `datetime` objects so we can sort the output DataFrame by Start time." ] }, { "cell_type": "code", "collapsed": false, "input": [ "psscandf = pd.DataFrame(taskinfo, columns=['Name', 'PID', 'PPID', 'Threads', 'HandleCount', 'SessionID', 'Wow64', 'Start', 'Exit'])\n", "psscandf.index = psscandf.PID\n", "psscandf['Start'] = pd.to_datetime(psscandf['Start'])\n", "psscandf['Exit'] = pd.to_datetime(psscandf['Exit'])\n", "\n", "psscandf.sort(['Start'])" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NamePIDPPIDThreadsHandleCountSessionIDWow64StartExit
PID
4 System 4 0 51 254 False NaT NaT
660 services.exe 660 616 15 -2121378248 False2008-11-15 23:42:56 NaT
592 csrss.exe 592 360 10 131072 False2008-11-15 23:42:56 NaT
828 svchost.exe 828 660 14 0 False2008-11-15 23:42:57 NaT
1016 svchost.exe 1016 660 51 0 False2008-11-15 23:42:57 NaT
924 svchost.exe 924 660 7 0 False2008-11-15 23:42:57 NaT
992 alg.exe 992 660 5 4784160 False2008-11-15 23:43:25 NaT
360 smss.exe 360 4 3 19 False2008-11-26 07:38:11 NaT
596 csrss.exe 596 360 10 322 False2008-11-26 07:38:13 NaT
620 winlogon.exe 620 360 16 503 False2008-11-26 07:38:14 NaT
672 services.exe 672 620 15 245 False2008-11-26 07:38:15 NaT
684 lsass.exe 684 620 21 347 False2008-11-26 07:38:15 NaT
932 svchost.exe 932 672 10 229 False2008-11-26 07:38:18 NaT
844 svchost.exe 844 672 19 198 False2008-11-26 07:38:18 NaT
1064 svchost.exe 1064 672 63 1308 False2008-11-26 07:38:20 NaT
1164 svchost.exe 1164 672 5 77 False2008-11-26 07:38:23 NaT
1264 svchost.exe 1264 672 14 209 False2008-11-26 07:38:25 NaT
1516 explorer.exe 1516 1452 12 362 False2008-11-26 07:38:27 NaT
1648 spoolsv.exe 1648 672 12 112 False2008-11-26 07:38:28 NaT
1904 VMwareUser.exe 1904 1516 1 28 False2008-11-26 07:38:31 NaT
1896 VMwareTray.exe 1896 1516 1 26 False2008-11-26 07:38:31 NaT
1756 VMwareService.e 1756 672 3 45 False2008-11-26 07:38:45 NaT
512 alg.exe 512 672 6 105 False2008-11-26 07:38:53 NaT
1372 wuauclt.exe 1372 1064 8 225 False2008-11-26 07:39:38 NaT
940 cmd.exe 940 1516 0 False2008-11-26 07:43:392008-11-26 07:45:49
560 wscntfy.exe 560 1064 1 31 False2008-11-26 07:44:57 NaT
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 8, "text": [ " Name PID PPID Threads HandleCount SessionID Wow64 Start Exit\n", "PID \n", "4 System 4 0 51 254 False NaT NaT\n", "660 services.exe 660 616 15 -2121378248 False 2008-11-15 23:42:56 NaT\n", "592 csrss.exe 592 360 10 131072 False 2008-11-15 23:42:56 NaT\n", "828 svchost.exe 828 660 14 0 False 2008-11-15 23:42:57 NaT\n", "1016 svchost.exe 1016 660 51 0 False 2008-11-15 23:42:57 NaT\n", "924 svchost.exe 924 660 7 0 False 2008-11-15 23:42:57 NaT\n", "992 alg.exe 992 660 5 4784160 False 2008-11-15 23:43:25 NaT\n", "360 smss.exe 360 4 3 19 False 2008-11-26 07:38:11 NaT\n", "596 csrss.exe 596 360 10 322 False 2008-11-26 07:38:13 NaT\n", "620 winlogon.exe 620 360 16 503 False 2008-11-26 07:38:14 NaT\n", "672 services.exe 672 620 15 245 False 2008-11-26 07:38:15 NaT\n", "684 lsass.exe 684 620 21 347 False 2008-11-26 07:38:15 NaT\n", "932 svchost.exe 932 672 10 229 False 2008-11-26 07:38:18 NaT\n", "844 svchost.exe 844 672 19 198 False 2008-11-26 07:38:18 NaT\n", "1064 svchost.exe 1064 672 63 1308 False 2008-11-26 07:38:20 NaT\n", "1164 svchost.exe 1164 672 5 77 False 2008-11-26 07:38:23 NaT\n", "1264 svchost.exe 1264 672 14 209 False 2008-11-26 07:38:25 NaT\n", "1516 explorer.exe 1516 1452 12 362 False 2008-11-26 07:38:27 NaT\n", "1648 spoolsv.exe 1648 672 12 112 False 2008-11-26 07:38:28 NaT\n", "1904 VMwareUser.exe 1904 1516 1 28 False 2008-11-26 07:38:31 NaT\n", "1896 VMwareTray.exe 1896 1516 1 26 False 2008-11-26 07:38:31 NaT\n", "1756 VMwareService.e 1756 672 3 45 False 2008-11-26 07:38:45 NaT\n", "512 alg.exe 512 672 6 105 False 2008-11-26 07:38:53 NaT\n", "1372 wuauclt.exe 1372 1064 8 225 False 2008-11-26 07:39:38 NaT\n", "940 cmd.exe 940 1516 0 False 2008-11-26 07:43:39 2008-11-26 07:45:49\n", "560 wscntfy.exe 560 1064 1 31 False 2008-11-26 07:44:57 NaT" ] } ], "prompt_number": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ "With the data in Pandas, we can filter with conditions like: _find all child processes of processes called svchost.exe_. First we filter the psscandf by Name and extract the unique PID values. Then we can go back to the dataframe and filter for any PPIDs that exist in that list." ] }, { "cell_type": "code", "collapsed": false, "input": [ "svchostpids = psscandf.ix[psscandf['Name'] == 'svchost.exe']['PID'].unique()\n", "svchostpids" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 9, "text": [ "array(['828', '1016', '924', '1164', '1264', '932', '844', '1064'], dtype=object)" ] } ], "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ "psscandf.ix[psscandf['PPID'].isin(svchostpids)]" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NamePIDPPIDThreadsHandleCountSessionIDWow64StartExit
PID
1372 wuauclt.exe 1372 1064 8 225 False2008-11-26 07:39:38NaT
560 wscntfy.exe 560 1064 1 31 False2008-11-26 07:44:57NaT
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 10, "text": [ " Name PID PPID Threads HandleCount SessionID Wow64 \\\n", "PID \n", "1372 wuauclt.exe 1372 1064 8 225 False \n", "560 wscntfy.exe 560 1064 1 31 False \n", "\n", " Start Exit \n", "PID \n", "1372 2008-11-26 07:39:38 NaT \n", "560 2008-11-26 07:44:57 NaT " ] } ], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or accomplish the same thing by joining the table to itself SQL-style." ] }, { "cell_type": "code", "collapsed": false, "input": [ "psscandf.ix[psscandf['Name'] == 'svchost.exe'].merge(psscandf, \n", " left_on=['PID'], \n", " right_on=['PPID'], \n", " suffixes=('_parent', '_child'))" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Name_parentPID_parentPPID_parentThreads_parentHandleCount_parentSessionID_parentWow64_parentStart_parentExit_parentName_childPID_childPPID_childThreads_childHandleCount_childSessionID_childWow64_childStart_childExit_child
0 svchost.exe 1064 672 63 1308 False2008-11-26 07:38:20NaT wuauclt.exe 1372 1064 8 225 False2008-11-26 07:39:38NaT
1 svchost.exe 1064 672 63 1308 False2008-11-26 07:38:20NaT wscntfy.exe 560 1064 1 31 False2008-11-26 07:44:57NaT
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 11, "text": [ " Name_parent PID_parent PPID_parent Threads_parent HandleCount_parent \\\n", "0 svchost.exe 1064 672 63 1308 \n", "1 svchost.exe 1064 672 63 1308 \n", "\n", " SessionID_parent Wow64_parent Start_parent Exit_parent Name_child \\\n", "0 False 2008-11-26 07:38:20 NaT wuauclt.exe \n", "1 False 2008-11-26 07:38:20 NaT wscntfy.exe \n", "\n", " PID_child PPID_child Threads_child HandleCount_child SessionID_child \\\n", "0 1372 1064 8 225 \n", "1 560 1064 1 31 \n", "\n", " Wow64_child Start_child Exit_child \n", "0 False 2008-11-26 07:39:38 NaT \n", "1 False 2008-11-26 07:44:57 NaT " ] } ], "prompt_number": 11 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The whole purpose of this sample image file __ds_fuzz_hidden_proc.img__ is to illustrate hidden processes. The __PSScan__ module we ran above will search through memory and find all processes. There is another module, __PSList__, that will walk the operating system's process tree and show every process you would see in Task Manager. Anything in PSScan that _isn't_ in PSList is an example of a hidden process.\n", "\n", "There are native tools in The Volatility Framework to highlight these discrepancies, but it's also easy enough for us to do it with Pandas for the sake of example. We already have PSScan output in the `psscandf` dataframe, now we build the same data structure based on PSList." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from volatility.plugins.taskmods import PSList\n", "\n", "psl = PSList(config)\n", "\n", "taskinfo = []\n", "\n", "for task in psl.calculate():\n", " info = {}\n", " info['Name'] ='%s' % task.ImageFileName\n", " info['PID'] = '%i' % task.UniqueProcessId\n", " info['PPID'] = '%i' % task.InheritedFromUniqueProcessId\n", " info['Threads'] = '%s' % task.ActiveThreads\n", " info['HandleCount'] = '%s' % task.ObjectTable.HandleCount\n", " info['SessionID'] = '%s' % task.SessionId\n", " info['Wow64'] = '%s' % task.IsWow64\n", " info['Start'] = str(task.CreateTime or '')\n", " info['Exit'] = str(task.ExitTime or '')\n", " \n", " taskinfo.append(info)\n", "\n", "pslistdf = pd.DataFrame(taskinfo, columns=['Name', 'PID', 'PPID', 'Threads', 'HandleCount', 'SessionID', 'Wow64', 'Start', 'Exit'])\n", "pslistdf.index = pslistdf.PID\n", "pslistdf['Start'] = pd.to_datetime(pslistdf['Start'])\n", "pslistdf['Exit'] = pd.to_datetime(pslistdf['Exit'])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "pslistdf" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NamePIDPPIDThreadsHandleCountSessionIDWow64StartExit
PID
4 System 4 0 51 254 False NaTNaT
360 smss.exe 360 4 3 19 False2008-11-26 07:38:11NaT
596 csrss.exe 596 360 10 322 0 False2008-11-26 07:38:13NaT
620 winlogon.exe 620 360 16 503 0 False2008-11-26 07:38:14NaT
672 services.exe 672 620 15 245 0 False2008-11-26 07:38:15NaT
684 lsass.exe 684 620 21 347 0 False2008-11-26 07:38:15NaT
844 svchost.exe 844 672 19 198 0 False2008-11-26 07:38:18NaT
932 svchost.exe 932 672 10 229 0 False2008-11-26 07:38:18NaT
1064 svchost.exe 1064 672 63 1308 0 False2008-11-26 07:38:20NaT
1164 svchost.exe 1164 672 5 77 0 False2008-11-26 07:38:23NaT
1264 svchost.exe 1264 672 14 209 0 False2008-11-26 07:38:25NaT
1516 explorer.exe 1516 1452 12 362 0 False2008-11-26 07:38:27NaT
1648 spoolsv.exe 1648 672 12 112 0 False2008-11-26 07:38:28NaT
1896 VMwareTray.exe 1896 1516 1 26 0 False2008-11-26 07:38:31NaT
1904 VMwareUser.exe 1904 1516 1 28 0 False2008-11-26 07:38:31NaT
1756 VMwareService.e 1756 672 3 45 0 False2008-11-26 07:38:45NaT
512 alg.exe 512 672 6 105 0 False2008-11-26 07:38:53NaT
1372 wuauclt.exe 1372 1064 8 225 0 False2008-11-26 07:39:38NaT
560 wscntfy.exe 560 1064 1 31 0 False2008-11-26 07:44:57NaT
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 13, "text": [ " Name PID PPID Threads HandleCount SessionID Wow64 Start Exit\n", "PID \n", "4 System 4 0 51 254 False NaT NaT\n", "360 smss.exe 360 4 3 19 False 2008-11-26 07:38:11 NaT\n", "596 csrss.exe 596 360 10 322 0 False 2008-11-26 07:38:13 NaT\n", "620 winlogon.exe 620 360 16 503 0 False 2008-11-26 07:38:14 NaT\n", "672 services.exe 672 620 15 245 0 False 2008-11-26 07:38:15 NaT\n", "684 lsass.exe 684 620 21 347 0 False 2008-11-26 07:38:15 NaT\n", "844 svchost.exe 844 672 19 198 0 False 2008-11-26 07:38:18 NaT\n", "932 svchost.exe 932 672 10 229 0 False 2008-11-26 07:38:18 NaT\n", "1064 svchost.exe 1064 672 63 1308 0 False 2008-11-26 07:38:20 NaT\n", "1164 svchost.exe 1164 672 5 77 0 False 2008-11-26 07:38:23 NaT\n", "1264 svchost.exe 1264 672 14 209 0 False 2008-11-26 07:38:25 NaT\n", "1516 explorer.exe 1516 1452 12 362 0 False 2008-11-26 07:38:27 NaT\n", "1648 spoolsv.exe 1648 672 12 112 0 False 2008-11-26 07:38:28 NaT\n", "1896 VMwareTray.exe 1896 1516 1 26 0 False 2008-11-26 07:38:31 NaT\n", "1904 VMwareUser.exe 1904 1516 1 28 0 False 2008-11-26 07:38:31 NaT\n", "1756 VMwareService.e 1756 672 3 45 0 False 2008-11-26 07:38:45 NaT\n", "512 alg.exe 512 672 6 105 0 False 2008-11-26 07:38:53 NaT\n", "1372 wuauclt.exe 1372 1064 8 225 0 False 2008-11-26 07:39:38 NaT\n", "560 wscntfy.exe 560 1064 1 31 0 False 2008-11-26 07:44:57 NaT" ] } ], "prompt_number": 13 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we take the list of PIDs from the PSList dataframe and filter the PSScan dataframe for any row where the PID is *not* in the PSList (via the ~ negation operator). Thus, we've discovered seven hidden processes! \n", "\n", "This particular memory sample was created to demonstrate a very clever technique to hide processes. In fact, there is another hidden process not shown in the list below. I'll leave that as an exercise for the reader. For more, see Jesse Kornblum's [blog post](http://jessekornblum.livejournal.com/289844.html)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "psscandf.ix[~psscandf.PID.isin(pslistdf.PID.tolist())].sort(['Start'])" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NamePIDPPIDThreadsHandleCountSessionIDWow64StartExit
PID
592 csrss.exe 592 360 10 131072 False2008-11-15 23:42:56 NaT
660 services.exe 660 616 15 -2121378248 False2008-11-15 23:42:56 NaT
828 svchost.exe 828 660 14 0 False2008-11-15 23:42:57 NaT
924 svchost.exe 924 660 7 0 False2008-11-15 23:42:57 NaT
1016 svchost.exe 1016 660 51 0 False2008-11-15 23:42:57 NaT
992 alg.exe 992 660 5 4784160 False2008-11-15 23:43:25 NaT
940 cmd.exe 940 1516 0 False2008-11-26 07:43:392008-11-26 07:45:49
\n", "
" ], "metadata": {}, "output_type": "pyout", "prompt_number": 14, "text": [ " Name PID PPID Threads HandleCount SessionID Wow64 \\\n", "PID \n", "592 csrss.exe 592 360 10 131072 False \n", "660 services.exe 660 616 15 -2121378248 False \n", "828 svchost.exe 828 660 14 0 False \n", "924 svchost.exe 924 660 7 0 False \n", "1016 svchost.exe 1016 660 51 0 False \n", "992 alg.exe 992 660 5 4784160 False \n", "940 cmd.exe 940 1516 0 False \n", "\n", " Start Exit \n", "PID \n", "592 2008-11-15 23:42:56 NaT \n", "660 2008-11-15 23:42:56 NaT \n", "828 2008-11-15 23:42:57 NaT \n", "924 2008-11-15 23:42:57 NaT \n", "1016 2008-11-15 23:42:57 NaT \n", "992 2008-11-15 23:43:25 NaT \n", "940 2008-11-26 07:43:39 2008-11-26 07:45:49 " ] } ], "prompt_number": 14 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Inline Graphing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The most exciting application of Volatility analysis in IPython Notebook, to me at least, is inline graphing. In addition to the primary `render_text` output option for the __PSScan__ module, there is also a `render_dot` for the [Graphviz dot](http://www.graphviz.org/Documentation.php) format. The typical Volatility use-case for Graphviz generation would go like this:\n", "\n", "1. Run `vol.py` with parameters `--output=dot --output-file=out.dot` \n", "2. Open the `out.dot` file in Graphviz \n", "3. Save the graph as an image\n", "\n", "In IPython, we can do that in just one step and keep the analysis, output, and documentation all in one place!\n", "\n", "To render the dot files, I'm using the IPython magic [`hierarchymagic`](https://github.com/tkf/ipython-hierarchymagic). This plugin adds a new IPython cell magic `%%dot` so you can write a cell like:\n", "\n", " %%dot\n", " digraph processtree { \n", " graph [rankdir = \"TB\"];\n", " pid672 -> pid844 [];\n", " pid672 -> pid932 [];\n", " //more cool dot stuff\n", " }\n", " \n", "and get the [SVG](http://en.wikipedia.org/wiki/Svg) output right in your notebook. We actually won't use this `%%dot` command, though. Instead, there's an underlying worker method called `run_dot` inside of `hierarchymagic` that we will use instead. We use the `render_dot` method to generate the graph in dot syntax. By importing the hierarchymagic library, we can pass the dot text directly to the `run_dot` method which returns SVG image data (which is just xml). Finally, IPython has a handy `SVG` method to render the graphic right in the notebook. No need to keep track of temporary files!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load_ext hierarchymagic\n", "import hierarchymagic #to put the library explicitly in the namespace\n", "from IPython.display import SVG" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 15 }, { "cell_type": "code", "collapsed": false, "input": [ "psdot = StringIO()\n", "psdata = ps.calculate()\n", "ps.render_dot(psdot, psdata)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 16 }, { "cell_type": "code", "collapsed": false, "input": [ "SVG(hierarchymagic.run_dot(psdot.getvalue(), format='svg'))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 17, "svg": [ "\n", "\n", "processtree\n", "\n", "\n", "pid672\n", "\n", "672\n", "\n", "services.exe\n", "\n", "running\n", "\n", "\n", "pid844\n", "\n", "844\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid844\n", "\n", "\n", "\n", "\n", "pid932\n", "\n", "932\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid932\n", "\n", "\n", "\n", "\n", "pid1756\n", "\n", "1756\n", "\n", "VMwareService.e\n", "\n", "running\n", "\n", "\n", "pid672->pid1756\n", "\n", "\n", "\n", "\n", "pid1064\n", "\n", "1064\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid1064\n", "\n", "\n", "\n", "\n", "pid1648\n", "\n", "1648\n", "\n", "spoolsv.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid1648\n", "\n", "\n", "\n", "\n", "pid1164\n", "\n", "1164\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid1164\n", "\n", "\n", "\n", "\n", "pid512\n", "\n", "512\n", "\n", "alg.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid512\n", "\n", "\n", "\n", "\n", "pid1264\n", "\n", "1264\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid672->pid1264\n", "\n", "\n", "\n", "\n", "pid1452\n", "\n", "pid1452\n", "\n", "\n", "pid1516\n", "\n", "1516\n", "\n", "explorer.exe\n", "\n", "running\n", "\n", "\n", "pid1452->pid1516\n", "\n", "\n", "\n", "\n", "pid940\n", "\n", "940\n", "\n", "cmd.exe\n", "\n", "exited\n", "2008-11-26 07:45:49\n", "\n", "\n", "pid1516->pid940\n", "\n", "\n", "\n", "\n", "pid1904\n", "\n", "1904\n", "\n", "VMwareUser.exe\n", "\n", "running\n", "\n", "\n", "pid1516->pid1904\n", "\n", "\n", "\n", "\n", "pid1896\n", "\n", "1896\n", "\n", "VMwareTray.exe\n", "\n", "running\n", "\n", "\n", "pid1516->pid1896\n", "\n", "\n", "\n", "\n", "pid360\n", "\n", "360\n", "\n", "smss.exe\n", "\n", "running\n", "\n", "\n", "pid596\n", "\n", "596\n", "\n", "csrss.exe\n", "\n", "running\n", "\n", "\n", "pid360->pid596\n", "\n", "\n", "\n", "\n", "pid592\n", "\n", "592\n", "\n", "csrss.exe\n", "\n", "running\n", "\n", "\n", "pid360->pid592\n", "\n", "\n", "\n", "\n", "pid620\n", "\n", "620\n", "\n", "winlogon.exe\n", "\n", "running\n", "\n", "\n", "pid360->pid620\n", "\n", "\n", "\n", "\n", "pid660\n", "\n", "660\n", "\n", "services.exe\n", "\n", "running\n", "\n", "\n", "pid828\n", "\n", "828\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid660->pid828\n", "\n", "\n", "\n", "\n", "pid992\n", "\n", "992\n", "\n", "alg.exe\n", "\n", "running\n", "\n", "\n", "pid660->pid992\n", "\n", "\n", "\n", "\n", "pid924\n", "\n", "924\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid660->pid924\n", "\n", "\n", "\n", "\n", "pid1016\n", "\n", "1016\n", "\n", "svchost.exe\n", "\n", "running\n", "\n", "\n", "pid660->pid1016\n", "\n", "\n", "\n", "\n", "pid0\n", "\n", "pid0\n", "\n", "\n", "pid4\n", "\n", "4\n", "\n", "System\n", "\n", "running\n", "\n", "\n", "pid0->pid4\n", "\n", "\n", "\n", "\n", "pid4->pid360\n", "\n", "\n", "\n", "\n", "pid1372\n", "\n", "1372\n", "\n", "wuauclt.exe\n", "\n", "running\n", "\n", "\n", "pid1064->pid1372\n", "\n", "\n", "\n", "\n", "pid560\n", "\n", "560\n", "\n", "wscntfy.exe\n", "\n", "running\n", "\n", "\n", "pid1064->pid560\n", "\n", "\n", "\n", "\n", "pid620->pid672\n", "\n", "\n", "\n", "\n", "pid684\n", "\n", "684\n", "\n", "lsass.exe\n", "\n", "running\n", "\n", "\n", "pid620->pid684\n", "\n", "\n", "\n", "\n", "pid616\n", "\n", "pid616\n", "\n", "\n", "pid616->pid660\n", "\n", "\n", "\n", "\n", "" ], "text": [ "" ] } ], "prompt_number": 17 }, { "cell_type": "markdown", "metadata": {}, "source": [ "\u00a9 2013 Lockheed Martin Corporation. All Rights Reserved." ] } ], "metadata": {} } ] }