Forensics
Step 242. Memory Forensics: Volatility 3 — How to Catch Evidence That Vanishes When the Power Goes Off
Level 3 — Forensics Track | Difficulty ★★★★☆ | Estimated time: 5 hours
Prerequisites: Step 239 (file signatures) complete. You know what a process is and how to search for strings (
strings).
⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.
- What you need: WSL Ubuntu + Python 3 (measured: 3.12).
/procaccess (root). - Caution: this environment has neither Volatility nor a practice memory image. All Volatility output is a "Screen example," while the principles of memory forensics — process lists, network connections, strings in memory — are measured live from Linux’s
/proc.
The moment you power off a computer at a crime scene, the contents of RAM evaporate. Yet the most important evidence — the malicious process running right now, the command just typed, a decrypted key, a password sitting in cleartext — lives only in RAM, not on disk. Memory forensics is the technique of freezing this volatile evidence into a dump and dissecting it. Today you learn the map of the standard tool Volatility 3, and verify the principles behind its plugins directly on a live Linux system.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Enumerate the kinds of evidence that exist only in memory (processes, connections, command lines, cleartext data)
- Reconstruct a process list and network connections by reading
/proc - Extract strings directly from another process’s memory
- Explain Volatility’s analysis order (
windows.info→pslist/psscan→pstree→ collection) - Know how the
pslist/psscandifference is used for rootkit detection
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | WSL Ubuntu bash + Python 3 (measured: Python 3.12) |
| Today’s tools | /proc/<pid>/ (comm, cmdline, maps, mem), /proc/net/tcp — all measured live |
| Concepts needed | Volatility, process memory maps, dumping, the Volatility plugin system (Screen example) |
| Today’s deliverable | A /proc observation script + "a secret string pulled from another process’s memory" |
2-1. Why Memory — The Things That Aren’t on Disk
Disk is the world of "what was stored"; memory is the world of "what’s happening right now." The representative list of evidence that exists only in RAM:
- Running processes and their command lines — including fileless malware that never exists as a file
- Live network connections — who the machine is talking to at this very moment
- Decrypted data — keys and strings that are encrypted on disk but cleartext while running
- Command history and clipboard — what the user just did
This is why the beginner’s mistake of "just power it off first" is fatal in incident response (IR). Cut the power and this entire list evaporates.
2-2. Dump and Dissection — A Two-Stage Division of Labor
Memory forensics splits into two stages. ① Dump: freeze the RAM at the moment of the incident into a single file (tools like WinPmem on Windows or LiME on Linux read at the kernel level). ② Dissection: restore meaning from that raw blob of bytes. A dump is just gigabytes of bytes, so you need a tool that knows "where the process list lives and what each process’s structures look like" — that tool is Volatility.
2-3. /proc — The Memory Window of a Live System
Linux already has the perfect practice window open. /proc is a virtual filesystem the kernel maintains, showing the state of the currently running system as if it were files:
| Path | Contents | Volatility counterpart |
|---|---|---|
/proc/<pid>/comm, cmdline |
Process name & command line | pslist, cmdline |
/proc/net/tcp |
Current TCP connection table | netstat |
/proc/<pid>/maps |
The process’s memory map | memmap |
/proc/<pid>/mem |
The actual contents of that memory | memmap --dump |
Today we read the same information from a live system instead of a dump file — because what Volatility does on a dead dump, /proc shows you directly on a living system.
2-4. Volatility 3 — The Plugin Map (Screen Example)
It’s not installed in this environment, but the real-world standard workflow looks like this (Screen example — not actually executed):
# Screen example — stage 0: identify the image's OS (the first step of every analysis)
$ vol -f memory.raw windows.info
Variable Value
Kernel Base 0xf8054b600000
NTBuildLab 19041.329.amd64fre.vb_release.190602-1739
# Screen example — stage 1: two kinds of process lists
$ vol -f memory.raw windows.pslist # follows the kernel's "current list"
PID PPID ImageFileName
4 0 System
512 4 smss.exe
3844 512 powershell.exe
$ vol -f memory.raw windows.psscan # sweeps all of memory for structure traces
PID PPID ImageFileName
...
5920 3844 evil.exe ← a process that wasn't in pslist!
The difference between the two lists is the key clue. pslist reads the operating system’s official registry; psscan scans all of memory for traces of process structures. A process that erased its own name from the official registry (a rootkit) appears only in psscan.
# Screen example — stage 2: collecting relationships and traces
$ vol -f memory.raw windows.pstree # parent-child: powershell.exe under winword.exe → the face of macro infection
$ vol -f memory.raw windows.cmdline # what command launched each process
$ vol -f memory.raw windows.netstat # network connections at dump time
$ vol -f memory.raw -o out/ windows.memmap --dump --pid 5920 # dump the suspicious process's memory to a file
$ strings out/pid.5920.dmp | grep -i "DH{" # find strings in it
Those last two lines — dumping a suspicious process’s memory and running strings over it — are exactly the job we’ll do ourselves today with /proc.
3. Follow Along
3-1. Staging the Incident — A Process Holding a Secret
Create a process that carries a secret only in memory (all local output in this chapter measured 2026-09-09 on WSL).
Input (victim.py)
import time, sys, os
SECRET = "DH{m3m0ry_n3v3r_f0rg3ts}" # this value really exists in the running process's RAM
print(f"[victim] PID={os.getpid()} holding a secret in memory, waiting...")
sys.stdout.flush()
time.sleep(120)
python3 victim.py &
[victim] PID=616 holding a secret in memory, waiting...
How to read it: this process writes no files and uses no network. The secret lives only in this process’s RAM. No matter how hard you search the disk, this running process’s variable value won’t turn up — it’s evidence you can only see by looking at memory.
3-2. Reconstructing the Process List — The Principle of pslist
Each numbered directory in /proc is one process. Read the names and command lines:
import os
for pid in sorted((p for p in os.listdir("/proc") if p.isdigit()), key=int):
try:
name = open(f"/proc/{pid}/comm").read().strip()
cmd = open(f"/proc/{pid}/cmdline", "rb").read().replace(b"