Post

Tool - VolProcSum

Summarizer for Volatility3's PsList and PsScan modules.

Tool - VolProcSum

Overview

Hello everyone, recently, I’ve developed a few utilities that I believe will be useful for my upcoming CTFs and could also prove valuable in real-world cases.

I’m excited to introduce my Volatility3 Process Summarizer! This tool provides a quick, high-level overview and basic analysis of CSV results generated by the PsList or PsScan modules of Volatility3.
The Process Summarizer extracts key values from the CSV file and, in addition, counts the child processes for each listed process, displaying their total number. This feature helps users quickly visualize process hierarchies. The tool also offers exploration options, allowing users to filter, sort, and refine the data for more in-depth analysis.
Finally, the tool offers the ability to export the results in various formats, including txt, csv, and json. This feature makes it easy to integrate the tool into a larger analysis workflow, which I’ll explore further in an upcoming article.

All default settings mentioned can be customized directly in the config.ini file, allowing for greater flexibility in how the tool is used

You can find the source code on my Github.

Please note: The script doesn’t utilize every parameter and data field from PsScan or PsList. It’s designed for a high-level overview, not a comprehensive, in-depth analysis.

Usage

To run the script, use the following command :

1
vol_ps_summary.py [FILE]

Where [FILE] refers to the CSV output from PsList or PsScan that you wish to summarize.

By default, the output will be displayed as a table containing all key information extracted for each process. This behavior can be modified using the options described in the following section.

Options

Summary

Option nameUsageDescription
Parameters--p [PARAMETERS]Orders the results based on the specified field
Filter--filter [PARAMETERS]Filters the results using the pandas query syntax.
Order-o [PARAMETERS]Saves the results to the specified file.
Render format--r [RENDER]Determine the output format.
Extract output--e [OUTFILE]Saves the results to the specified file.
Table format--tblfmt [TBLFMT]Changes the table format of the output.
Inverse order--inv_ordReverses the default ordering.
No space--no_spaceRemoves spaces at the beginning and end of the output.
No count--no_countPrevents the count section from being printed.
No index--no_indexRemoves the index from CSV and JSON output formats.

Parameters

1
vol_ps_summary.py [FILE] -p or --parameters [PARAMETERS]
  • Utility : Display only specific parameters from the results. This is particularly useful if you want to focus on certain details, such as the PIDs or process names.
  • Choices : [PARAMETERS] are defined by the d_parameters in the config.ini file. By default, the options include name, time, ppid, pid and subp.
  • Default : if no parameters are specified, all parameters will be displayed.

Filter

1
VolProcSum.py [FILE] --filter [QUERY]
  • Utility : Apply a filter to the results. [QUERY] uses the pandas query syntax and also supports the use of the Python in operator.
  • Choices : Queries are allowed on the values defined by the d_parameters in the config.ini. By default, the options include name, time, ppid, pid and subp.
  • Default : No query.

Order

1
VolProcSum.py [FILE] -o or --order [ORDER]
  • Utility : Orders the results based on the field specified by [ORDER].
  • Choices : [ORDER] can be one of the values defined by the d_parameters in the config.ini. By default, the options include name, time, ppid, pid and subp.
  • Default : No ordering. If specified, the default order is ascending, but it can be reversed using the --inv-order parameter.

Render

1
VolProcSum.py [FILE] -r or --render [RENDER]
  • Utility : Change the output format.
  • Choices : [RENDER] can be one of the values defined by the output_formats in the config.ini. By default, the options include txt, csv, json and tab.
  • Default : Default value is tab.

Save output

1
VolProcSum.py [FILE] -e or --extract [OUTFILE]
  • Utility : Saves the results to the file specified by [OUTFILE]. The output format follows the one defined by the render option.
  • Default : If no output file is specified, the results are printed to the standard output, unless the --quiet option is enabled.

Other options

No space

1
VolProcSum.py [FILE] --no_space
  • Utility : Prevents spaces from being added at the beginning and end of the output. This can be useful when redirecting results.
  • Default : By default, spaces are added for better readability in the standard output.

No count

1
VolProcSum.py [FILE] --no_count
  • Utility : Prevents the count section from being printed at the end. This can be useful when redirecting results.
  • Default : By default, the count section is included, showing the total number of processes and the number of displayed processes. This behavior can be modified via the d_count parameter in config.ini.

No index

1
VolProcSum.py [FILE] --no_index
  • Utility : Removes the index from CSV and JSON output formats.
  • Default : By default, the index is included.

Table format

1
VolProcSum.py [FILE] --tblfmt [TBLFMT]
  • Utility : Modifies the table format of the output.
  • Choices : Allowed values are those supported by the tabulate Python module.
  • Default : The default format is github and it can be changed with the d_tablefmt parameter in config.ini.

Example

To better understand how it works, let’s explore a concrete example. First, we’ll run the script without specifying any options to observe the default output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
VolProcSum.py test.csv

# === OUTPUT ===

|     | Name      | Time                           | PPID | PID | Subprocesses |
| --- | --------- | ------------------------------ | ---- | --- | ------------ |
| 0   | System    | 2025-01-03 16:50:11.000000 UTC | 0    | 4   | 0            |
| 1   | smss.exe  | 2025-01-03 16:50:11.000000 UTC | 4    | 260 | 1            |
| 2   | csrss.exe | 2025-01-03 16:50:12.000000 UTC | 356  | 364 | 1            |
| 6   | lsass.exe | 2025-01-03 16:50:13.000000 UTC | 444  | 556 | 0            |
[...]
| 22  | firefox.exe    | 2025-01-03 16:55:40.000000 UTC | 4060 | 3036 | 25     |
[...]
| 28  | WmiPrvSE.exe   | 2025-01-03 17:11:13.000000 UTC | 628  | 4124 | 1      |

Count: 29
Total: 29

As we can see, the script lists all the extracted information for each process. Some processes have no subprocesses, while others have many. To focus on those with at least one child process, we can apply a filter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
VolProcSum.py test.csv --filter "subp > 0"

# === OUTPUT ===

|     | Name         | Time                           | PPID | PID  | Subprocesses |
| --- | ------------ | ------------------------------ | ---- | ---- | ------------ |
| 1   | smss.exe     | 2025-01-03 16:50:11.000000 UTC | 4    | 260  | 1            |
| 2   | csrss.exe    | 2025-01-03 16:50:12.000000 UTC | 356  | 364  | 1            |
| 7   | svchost.exe  | 2025-01-03 16:50:13.000000 UTC | 548  | 628  | 14           |
| 22  | firefox.exe  | 2025-01-03 16:55:40.000000 UTC | 4060 | 3036 | 25           |
| 28  | WmiPrvSE.exe | 2025-01-03 17:11:13.000000 UTC | 628  | 4124 | 1            |

Count: 5
Total: 29

Now, to improve clarity, we might want to order the results based on the number of subprocesses. Since I prefer an descending order, I’ll invert the default sorting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
VolProcSum.py test.csv --filter "subp > 0" -o subp

# === OUTPUT ===

|     | Name         | Time                           | PPID | PID  | Subprocesses |
| --- | ------------ | ------------------------------ | ---- | ---- | ------------ |
| 22  | firefox.exe  | 2025-01-03 16:55:40.000000 UTC | 4060 | 3036 | 25           |
| 7   | svchost.exe  | 2025-01-03 16:50:13.000000 UTC | 548  | 628  | 14           |
| 1   | smss.exe     | 2025-01-03 16:50:11.000000 UTC | 4    | 260  | 1            |
| 2   | csrss.exe    | 2025-01-03 16:50:12.000000 UTC | 356  | 364  | 1            |
| 28  | WmiPrvSE.exe | 2025-01-03 17:11:13.000000 UTC | 628  | 4124 | 1            |

Count: 5
Total: 29

I want to keep only the name, pid, and subp columns. Additionally, I don’t need the count section or extra spaces, so I’ll remove them.

1
2
3
4
5
6
7
8
9
10
VolProcSum.py test.csv --filter "subp > 0" --order subp --inv_order --parameters name, pid, subp --no_count --no_space

# === OUTPUT ===
|     | Name         | PID  | Subprocesses |
| --- | ------------ | ---- | ------------ |
| 22  | firefox.exe  | 3036 | 25           |
| 7   | svchost.exe  | 628  | 14           |
| 1   | smss.exe     | 260  | 1            |
| 2   | csrss.exe    | 364  | 1            |
| 28  | WmiPrvSE.exe | 4124 | 1            |

At this point, we could directly redirect the output to a .txt file using a redirection operator like >. However, I ultimately want to export the results as a CSV file without the index.

1
2
3
4
5
6
7
8
9
VolProcSum.py test.csv --filter "subp > 0" --order subp --inv_order --parameters name, pid, subp --no_count --no_space --no_index -r csv -e out.csv

# CSV file
name,pid,subp
firefox.exe,3036,25
svchost.exe,628,14
smss.exe,260,1
csrss.exe,364,1
WmiPrvSE.exe,4124,1

Future Improvements

  • Add a feature to list a parent process along with its child processes.
  • Improve error handling.

Conclusion

This script is fairly simple and is mainly designed to provide a quick overview of the processes running in a memory capture. However, it allows us to easily identify the most important processes and, if needed, export the results effortlessly.

This tool is part of a broader toolkit I’m building. I hope this guide was clear and that you find the script useful ! See you in the next one !

emree1

This post is licensed under CC BY 4.0 by the author.