Sitemap

Volatility — Memory Forensics

15 min readJul 27, 2026

--

Volatility 2 and 3 have some genuinely frustrating setup quirks that aren’t documented clearly anywhere. Here’s everything worth knowing.

Volatility 3 requires Python 3.8 or higher. Volatility 2 requires Python 2.7 — and Python 2.7 is end-of-life, meaning it’s getting harder to install cleanly on modern systems. If you’re on Kali Linux or Ubuntu 22+, Python 2.7 may not even be in the default package manager anymore. The safest approach is to keep them in completely separate environments and never mix them.

The most common beginner mistake is running python vol.py when Python 3 is the default on the system — if vol.py is the Volatility 2 version, it will break immediately. Always be explicit: python2 vol.py for Volatility 2, python3 vol.py for Volatility 3.

Volatility 2 needs profiles, Volatility 3 does not — and this changes everything

In Volatility 2, every command requires --profile=Win7SP1x64 or whatever matches the OS. If you get the profile wrong, every plugin output will be garbage or empty. Finding the right profile was done with imageinfo or kdbgscan, which could take several minutes to run.

Why profiles are necessary?

The internal data structures Windows uses — like EPROCESS (the process structure), ETHREAD, _KDDEBUGGER_DATA64 — are not the same across OS versions. Microsoft changes them between releases. A field that sits at byte offset 24 inside EPROCESS on Windows 7 might sit at byte offset 40 on Windows 10. The structure gets bigger, fields get added, removed, or reordered with each major version and service pack.

Volatility 2 needed to know exactly where each field was inside each structure so it could correctly parse the raw bytes in memory. The mapping — “for this OS version, here is the exact layout of every kernel structure” — is what a profile contained. A profile is the precise description of how Windows kernel structures are laid out for one specific OS version.

Profiles are necessary because the same memory bytes mean different things depending on the Windows version, and the profile tells Volatility how to interpret them correctly.

wait, what is KDDEBUGGER_DATA64?

Windows maintains a special structure in kernel memory called the KDDEBUGGER_DATA64 block (shortened to KDBG). This structure is essentially Windows’ own internal index — it contains pointers to critical kernel data structure like the process list, module list, and other OS internals. Volatility 2 needed to find this block first before it could walk any of those structures.

imageinfo was the simple profile-detection plugin. It would find the KDBG, read the build string embedded in it, and suggest matching profiles. But imageinfo only found the most obvious KDBG — and malware, particularly rookits, sometimes overwrote or obfuscated the KDBG to blind memory forensics tool. And if the profile is wrong, offsets are wrong, structure was misread, and output becomes nonsense. When imageinfo gave wrong results or no results, kdbgscan was the fallback.

kdbgscan worked differently — instead of finding one KDBG and trusting it, it scanned the entire memory image looking for every possible KDBG signature.

What do you mean by looking for every possible KDBG signature?

kdbgscan looks for patterns/signatures of KDBG. It looks for byte patterns and structural clues in memory that resemble what a real KDBG should look like. A real KDBG has predictable characteristics: known structure layout (from profiles like specific fields, expected sizes, known ordering patterns), magic values/tags (debugger-related constants), and valid kernel pointers.

It would return multiple candidates with confidence scores, letting you try each one until the plugins produced sensible output.

Even if profile is not found, run kpcrscan scans memory for Kernel Processor Control Region (KPCR) . It is a per-CPU structure that stores critical processor-specific kernel data. Each CPU/core has its own KPCR. KPCR contains pointer to current thread, pointer to current process, CPU specific data and interrupt handling info. Basically, it links to KDBG, check CPU count, verify kernel integrity. If KDBG is tampered with, KPCR can provide another path into kernel data.

kpcrscan scans memory for KPCR structures, which give per-CPU entry points into the Windows kernel and can help validate or recover analysis when KDBG is unreliable.

Why this mechanism?

When Windows boots, the kernel builds this KDBG structure and fills it with pointers — “the process list starts at index x, the loaded list starts at address Y, the handle table is at address Z.” Windows itself uses these pointers internally for debugging purposes.

Volatility 2 essentially hijacked this same mechanism. Instead of having its own map of where kernel structures live it, it found the KDBG first and then read all those pointers from it. Every single plugin — pslist, dlllist, handles, everything — was downstream of that one starting point.

Memory dump
→ kdbgscan / imageinfo finds the KDBG block
→ KDBG contains pointer to EPROCESS list
→ pslist walks that EPROCESS list → shows processes
→ KDBG contains pointer to module list
→ dlllist reads that list → shows loaded DLLs
→ KDBG contains pointer to handle table
→ handles reads that → shows open handles

The symbol table approach (Volatility 3) — calculate from known offsets

Imagine RAM as a giant book written in a language only the operating system understands. The writing has no spaces — it is one continuous stream of numbers. Volatility3’s job is to read that book and find where each chapter begins. But the main problem is, it doesn’t automatically know how the OS organized that memory. The symbol table is the key
It tells Volatility3 things like: “process looks like this structure”, defines data structure, maps names to memory layouts. Symbol table is specific to an OS version + build. Different OS versions store things differently.
This table acts like a dictionary for the OS it is reading. Volatility3 is rewritten in Python 3 and uses a smarter approach — it reads structured symbol files (called ISF files) that contain exact memory layout information. This makes it more accurate and easier to extend, but it does require those symbol files to exist for your exact kernel version

Vol3 has built-in detectors for: Windows, Linux, and macOS. Each one tries to recognize its own signature and structures. It looks for kernel base patterns, page tables, known kernel structures and then loads Microsoft symbol files (PDBs). It uses them to interpret structures dynamically.

For linux detection, it searches for: kernel banner string (linux version …), kernel symbol tables, and task structures. If these line up, Linux confirmed.

Memory Image
↓
Kernel Identification
↓
Find matching symbols
↓
Load ISF table
↓
Parse structures dynamically

Volatility 3 eliminated this entirely. It auto-detects the OS by downloading symbol files from Microsoft’s public symbol server. This means your first run on a new dump requires an internet connection to pull the symbols. If you’re in an air-gapped lab (common in CTFs and real investigations), you need to pre-download symbols and place them in volatility3/symbols/. The symbols live at https://downloads.volatilityfoundation.org/volatility3/symbols/ — download the Windows, Mac, or Linux packs ahead of time.

Why Installation in Linux is Harder?

When you install Volatility3 on Windows and try to analyze a Windows memory image, it mostly works. You download a symbol pack, point Volatility at it, and run plugins. On Linux, you try to analyze a Linux memory image and Volatility3 says it cannot find a symbol table, or the plugin fails with a strange error. Why?

Why Windows is Easier?

Microsoft ships Windows in a small number of well-known versions. Windows 10 21H2, Windows 11 22H2, and so on. The Volatility Foundation has pre-built symbol tables for all of these versions and hosts them as downloadable files. You download the right one and use it.

Why Linux Is Harder?

Linux is not one operating system — it is thousands. Every distribution (Ubuntu, Fedora, Arch, Kali, Debian) compiles its own kernel. Every time the kernel version changes — even a minor security patch — the internal memory layout changes slightly

Ubuntu 22.04 with kernel 5.15.0–91 has a different memory layout than Ubuntu 22.04 with kernel 5.15.0–92. They are both Ubuntu 22.04, but Volatility3 cannot use the same symbol table for both.

What This Means Practically

You will need to: • Find out your exact kernel version • Get the debug information file for that exact kernel from your distribution • Use a tool called dwarf2json to convert that debug information into a symbol table • Place the symbol table where Volatility3 can find it

Debug Information and DWARF?

When programmers compile software, they can include extra information for debugging purposes — information that describes every structure, every variable, every function, and where they live in memory. Basically, metadata about how the operating system kernel was compiled — especially: structure layouts, variable offsets, function symbols, and type definitions.

DWARF (Debugging with Attributed Record Formats) is the standard format for this debug information on Linux. It is not a program — it is a format, like how JPEG is a format for images.

The kernel debug information in DWARF format describes every kernel structure in precise detail — exactly what Volatility3 needs.

vmlinux — The Debug Kernel File

When the Linux kernel is compiled, two files are produced. The first is a small compressed file (vmlinuz) that actually boots your computer. The second is a large uncompressed file called vmlinux that contains the full kernel with all debug information.

vmlinuz is what runs on your system. vmlinux is the debug version — it contains the DWARF debug information that describes every structure. It is very large (often 400–600 MB) and not used at runtime.

Your distribution packages the vmlinux file separately in a debug symbols package. You must install that package to get access to the debug information.

ISF — Intermediate Symbol Format

ISF is Volatility3’s own file format for symbol tables. It is a JSON file (readable text) that contains:

  • The names of all kernel structures • The size of each structure in bytes • The offset of every field within each structure • The names and addresses of important kernel functions and variables

Volatilty3 reads ISF files at startup. Once it has an ISF file, it knows everything about the kernel’s memory layout and can parse a memory image from that kernel.

dwarf2json — The Translation Tool

dwarf2json is a small Go program that reads a vmlinux file (which contains DWARF debug information) and outputs an ISF JSON file. It is the bridge between the kernel’s debug information and Volatility 3. You can run it once per kernel version. The output is a .json.xz file (compressed JSON) that you place in Volatility3’s symbol directory.

Symbol Table

A symbol table is the ISF file — or more loosely, any collection of information that maps names to memory addresses and layouts. When people say Volatility3 cannot find a symbol table, they mean it cannot find the ISF file for the kernel version of the memory image you are analyzing

What You Need Before Installation

Prerequisites and system requirements

Press enter or click to view image in full size

Before doing anything else, confirm Python 3 is available and is version 3.7 or higher.

You need your exact kernel version for the symbol table step. Get it now and write it down.

The string after uname -r is your kernel version. Every character matters. 5.15.0–91-generic and 5.15.0–92-generic are different kernels with different symbol tables.

Volatility3 analyzes saved memory dumps — it does not read live RAM by itself. You need a memory image file to analyze.

Get SAFAL GAUTAM’s stories in your inbox

Join Medium for free to get updates from this writer.

Common sources: • Practice / learning: Download sample memory images from MemLabs (GitHub) or CyberDefenders • VM snapshots: VMware .vmem files and VirtualBox .elf files work directly • Linux live capture: Use LiME (Linux Memory Extractor) — a kernel module that dumps RAM to a file • CTF competitions: Usually provided as part of the challenge.

Important: The symbol table you build must match the kernel of the machine whose memory you are analyzing — not necessarily your own machine’s kernel. If you are analyzing a memory image from Ubuntu 22.04 with kernel 5.15.0–91-generic, you need the symbol table for that kernel, even if your analysis machine runs a different kernel

Installing Volatility 3 — Step by Step

Install System Dependencies

Volatility3 is written in Python but some of its components need system libraries. Install them first.

**

Install Volatility 3 from Source

Installing from source gives you the latest plugins, lets you add custom plugins, and makes it easier to understand how the tool works. This is what most practitioners do.

# Clone the repository
git clone https://github.com/volatilityfoundation/volatility3.git
cd volatility3
# Create and activate a virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install --upgrade pip
pip install -r requirements.txt
# Optional: install dev dependencies for extended plugins
pip install -r requirements-dev.txt
# Test the install
python vol.py --help

Understanding the Directory Structure

After cloning from source, here is what the directory contains and why each part matters:

volatility3/
vol.py #the main script you run
framework/ #core engine -- do not edit
plugins/ #analysis plugins (pslist, netscan, etc)
symbols/ #THIS IS WHERE SYMBOL TABLES GO
windows/ #Windows symbol tables (.json.xz files)
linux/ #Linux symbol tables (.json.sz files)
mac/ #macOS symbol tables
requirements.txt #Python dependencies list
setup.py #install script

Dependencies that commonly break

For Volatility 2, the pycrypto library is required for hashdump and many other plugins. pycrypto is abandoned and doesn't compile cleanly on modern systems — use pycryptodome instead, which is a drop-in replacement. Install it with pip2 install pycryptodome. Without it, about a third of Vol2 plugins silently fail or throw import errors.

For Volatility 3, yara-python is required for yarascan. It's not installed by default. Run pip3 install yara-python separately — it requires the yara C library to be present on the system first (sudo apt install yara on Debian/Ubuntu).

The full recommended Volatility 3 dependency install looks like this:

sudo apt install yara
pip3 install yara-python pycryptodome capstone
pip3 install -r requirements.txt

Memory dump format compatibility

Both versions handle .raw, .vmem, .mem, .dmp, and .lime natively. However, .E01 (EnCase forensic image format, the same format Autopsy uses) requires an extra library. For Volatility 3, install pyewf to handle E01 files. Without it, Volatility will simply say it cannot open the file with no further explanation, which is confusing.

For .vmem files from VMware, you also need the .vmss or .vmsn (snapshot state) file in the same directory — the .vmem alone is incomplete metadata-wise, though Vol3 handles it more gracefully than Vol2.

Running Vol2 vs Vol3 command syntax difference

This trips people up constantly:

# Volatility 2
python2 vol.py --profile=Win10x64_19041 -f mem.raw pslist
# Volatility 3
python3 vol.py -f mem.raw windows.pslist

In Vol2, the profile comes before the filename. In Vol3, the filename always comes immediately after -f and plugins use dot notation with the OS prefix. If you find a command online and it has --profile= in it, it's a Volatility 2 command.

Output and performance considerations

Volatility is slow on large dumps (8GB+ files). psscan, filescan, and netscan in particular do full memory scans and can take 10–30 minutes on large images. Redirect output to files rather than reading in the terminal — > output.txt — so you don't lose results. For CTF work especially, run all your heavy plugins first with output redirected, then analyze the text files at your pace.

On low-RAM machines, Volatility can itself run out of memory analyzing a large dump. Give it at least 2x the dump size in free RAM. On a 4GB dump you want at least 8GB available on the analysis machine.

One practical thing that saves a lot of time — create a simple bash script that runs your standard first-phase plugins all at once and saves them to a folder:

The Hard Part: Getting Your Linux Symbol Table

This is the chapter that most guides skip over. We will go through it completely. By the end, you will have a working ISF symbol table for your Linux kernel.

The Two Approaches

Approach A saves time if it works. Approach B always works but takes more steps. We cover both. Most people end up needing Approach B.

Approach A — Check for Pre-Built ISF Files

The Volatility Foundation hosts some pre-built Linux symbol tables. Check first before building your own.

# Check the official downloads page:
https://downloads.volatilityfoundation.org/volatility3/symbols/
# Also check the community Linux ISF repository:
https://github.com/Abyss-W4tcher/volatility3-symbols
# Your kernel version (from Chapter 4):
uname -r
# Look for a file matching your kernel version in those repositories.
# The filename will look like:
ubuntu-5.15.0-91-generic.json.xz

If you find a matching file, download it and skip to section (Placing the ISF File). If not, continue with Approach B.

Approach B Step 1 — Install the Kernel Debug Package

Your distribution ships a debug symbol package for the kernel. This package contains the vmlinux file — the large uncompressed kernel with DWARF debug information. You must install it.

Ubuntu / Debian: Ubuntu uses a special repository called ddebs (Debug DEBs) for debug packages.

# Step 1: Add the ddebs repository (if not already added)
echo 'deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe
multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted
universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted
universe multiverse' |
sudo tee /etc/apt/sources.list.d/ddebs.list
# Step 2: Import the signing key
sudo apt install ubuntu-dbgsym-keyring
# Step 3: Update package lists
sudo apt update
# Step 4: Get your exact kernel version
uname -r
# Example: 5.15.0-91-generic
# Step 5: Install the debug package (replace VERSION with your output from
uname -r)
sudo apt install linux-image-$(uname -r)-dbgsym
# Wait — this downloads 400-700 MB

Fedora / RHEL:

# Install kernel debug info
sudo dnf install kernel-debuginfo-$(uname -r)
# Or using debuginfo-install
sudo debuginfo-install kernel-$(uname -r)

Kali Linux:

# 1. Add the Kali debug symbols repository
echo "deb http://http.kali.org/kali kali-rolling main contrib non-free" | sudo tee /etc/apt/sources.list

# 2. Enable dbgsym packages for Kali
echo "deb http://kali.download/kali kali-rolling/main amd64 Packages" | sudo tee -a /etc/apt/sources.list.d/kali.list

# 3. Update
sudo apt update

# 4. Install the correct debug symbols for your kernel (6.18.12+kali-amd64)
sudo apt install linux-image-6.18.12-kali-amd64-dbg
# Kali uses Debian debug packages
sudo apt install linux-image-$(uname -r)-dbg
# If not available, try:
sudo apt install linux-image-$(uname -r)-dbgsym

Approach B Step 2— Find the vmlinux file

# Ubuntu/Debian: vmlinux is usually in /usr/lib/debug/boot
ls /usr/lib/debug/boot
#You should see: vmlinux-5.15.0-91-generic

#FEDORA/RHEL: vmlinux is usually in /usr/lib/debug/lib/modules
ls /usr/lib/debug/lib/modules/$(uname -r)/
#You should see: vmlinux

#Confirm it is the right file:
file /usr/lib/debug/boot/vmlinux-$(uname -r)

#Should say: ELF 64-bit LSB executable ... not stripped
# 'not strippped' means the debug info is present

If file says ‘stripped’: The debug info has been removed and this file is useless for generating symbols. You installed the wrong package or your distribution does not provide debug symbols for this kernel version. Try a different repository or search for your distribution’s specific instructions for dbgsym packages.

Approach B Step 3— Install Go and dwarf2json

dwarf2json is written in Go. You must install the Go programming language runtime first. then build dwar2json from source.

Install Go:

# Download Go (check golang.org for the latest version)
wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz
# Extract to /usr/local
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
# Add Go to your PATH (add this line to ~/.bashrc or ~/.zshrc)
export PATH=$PATH:/usr/local/go/bin
# Reload shell
source ~/.bashrc
# Verify Go is installed
go version
# Expected: go version go1.21.0 linux/amd64

Build dwarf2json:

# Clone dwarf2json
git clone https://github.com/volatilityfoundation/dwarf2json.git
cd dwarf2json
# Build it
go build .
# Verify it was built
ls -la dwarf2json
# You should see a binary file called 'dwarf2json'
# Make it accessible system-wide (optional but convenient)
sudo cp dwarf2json /usr/local/bin/

Approach B Step 4— Generate the ISF Symbol Table

Now you have everything needed. Run dwarf2json to convert the vmlinux debug information into a Volatility3 ISF file.

Before running: This step takes 2–10 minutes and produces a large output file (often 30–100 MB uncompressed). Make sure you have disk space. The compressed output is much smaller

# Set your kernel version as a variable for convenience
KERNEL=$(uname -r)
echo "Kernel version: $KERNEL"
# Ubuntu/Debian path
VMLINUX=/usr/lib/debug/boot/vmlinux-$KERNEL
# Fedora/RHEL path (use this instead on Fedora)
# VMLINUX=/usr/lib/debug/lib/modules/$KERNEL/vmlinux
# Confirm the file exists and is not stripped
file $VMLINUX
# Run dwarf2json — this generates the ISF file
dwarf2json linux --elf $VMLINUX > $KERNEL.json
# Compress it (Volatility3 accepts .json.xz files)
xz -9 $KERNEL.json
# You now have a file called: 5.15.0-91-generic.json.xz (example)
ls -lh $KERNEL.json.xz

What is happening during this step? dwarf2json reads every structure definition from the vmlinux DWARF debug info and writes them in JSON format. The xz command then compresses it. Volatility3 reads .json.xz files directly — it decompresses them automatically

Place the ISF File Where Volatility3 Can Find It

Volatility3 looks for Linux symbol tables in a specific directory. You must place your generated ISF file there.

KERNEL=$(uname -r)
# If installed from source (adjust path to where you cloned vol3):
cp $KERNEL.json.xz ~/volatility3/volatility3/symbols/linux/
# Verify it is there:
ls ~/volatility3/volatility3/symbols/linux/
# Should show your .json.xz file

Testing That Everything Works

# If installed from source:
cd ~/volatility3
source venv/bin/activate
python vol.py --help
# If installed via pip:
vol --help
# Expected: a long help message listing all available plugins

Volatility 2 and 3 aren’t just different tools, they’re two different philosophies for the same problem — how do you make sense of raw memory bytes without any labels. Knowing which philosophy you’re using, and why, is the difference between running commands and actually understanding memory forensics.

--

--

SAFAL GAUTAM
SAFAL GAUTAM

Writing from the edge of curiosity.