Memory Forensics Cheatsheet
RAM is where the malware actually runs. The Volatility 3 plugins by what you are hunting, process injection, credential theft, fileless malware, persistence, kernel rootkits, and Linux, with what each one reveals and the tells that confirm a finding. No account needed.
Memory is the one place a running attack cannot fully hide: injected code, decrypted payloads, live network connections, and the processes a rootkit conceals from the operating system are all present in RAM even when the disk and the live tools show nothing. The cost is that memory is volatile and acquisition is one-shot, you capture it once, at the right moment, or it is gone. These commands use Volatility 3; the syntax is vol -f <image> <plugin>.
Why memory is ground truth
Disk forensics tells you what was stored; memory forensics tells you what was running. The gap between them is exactly where modern malware lives: fileless payloads that never touch disk, code injected into legitimate processes, credentials cached in LSASS, and rootkits that edit the kernel's own view so that ps, netstat, and the task list lie. Memory is also the only source for the decrypted form of something the disk holds only encrypted. The discipline is to acquire first and analyze offline, because every tool you run on the live host changes the memory you are trying to preserve.
| Only in memory | Why disk misses it |
|---|---|
| Injected / hollowed code | Lives inside a legitimate process's address space; the file on disk is benign. |
| Fileless malware | Executes from memory (script, reflective load); never written to disk to find. |
| Decrypted payloads / keys | The disk holds the encrypted form; the running process holds the plaintext. |
| Live network state | Connections and sockets exist in kernel memory, gone at shutdown. |
| Rootkit-hidden objects | Hidden from the OS but present in the raw structures memory analysis scans. |
Acquisition and first steps
Acquisition captures RAM to an image with the smallest possible footprint, then all analysis happens offline against that file, never on the live host, because every tool you run there overwrites the memory you are trying to preserve. Acquire as early as possible: memory changes by the second, and a process you wait to capture may exit, taking its evidence with it. First step on any image is to identify it. windows.info (or linux.banner) confirms the OS and build so Volatility loads the right symbol table; get this wrong and every subsequent plugin returns garbage or nothing, which examiners new to memory forensics often mistake for a clean result rather than a wrong profile.
| Step | Plugin / tool |
|---|---|
| Acquire (Windows) | WinPmem, Magnet RAM Capture, or a hypervisor snapshot (.vmem). |
| Acquire (Linux) | AVML (static binary) or LiME (kernel module); image to external media. |
| Identify the image | windows.info / linux.banner, confirm OS and build before anything else. |
| Triage order | Processes, then network, then injection, then dig, broad to specific. |
Process analysis
Processes are the spine of a memory investigation, and the first questions are always the same: what is running, what launched it, and is anything hiding. windows.pslist walks the OS process list, the same view the live task list shows; windows.psscan ignores that list and scans raw memory for process structures directly. The power is in the comparison: a process in psscan but not pslist has been unlinked from the OS list, deliberately hidden by a rootkit, and that divergence is one of the highest-value findings in all of memory forensics because it points straight at active concealment. psscan also recovers terminated processes whose structures have not yet been overwritten, so it can show you what ran and exited before you captured. windows.pstree renders parentage so an implausible chain (services.exe spawning cmd.exe) jumps out, and windows.cmdline gives the full launch command, where encoded PowerShell and tell-tale arguments live.
| Plugin | Reveals |
|---|---|
| windows.pslist | Processes via the OS linked list, what the system thinks is running. |
| windows.psscan | Processes by scanning raw memory; finds the hidden and the terminated. |
| windows.pstree | Parent-child tree; spot the implausible parent (services.exe spawning cmd). |
| windows.cmdline | Full command line per process; encoded PowerShell and odd arguments. |
Process injection
Injection hides malicious code inside a legitimate process, so the process name, its signature, and the file on disk are all innocent, which is precisely why it defeats disk forensics and most allowlisting. windows.malfind is the workhorse here: it flags memory regions that are executable and writable (RWX) and not backed by any file on disk, which is the structural signature of injected or reflectively-loaded code, because normal executable code is mapped read-only from a file, not written into private memory at runtime. malfind produces false positives (some legitimate JIT compilers use RWX), so the judgment is context: a RWX region with an MZ or PE header inside a process that has no reason to hold executable private memory, a browser, an Office app, the print spooler, is the lead worth dumping and analyzing. Hollowing is the subtler cousin: the process started legitimately, then had its image replaced, so pslist looks entirely normal and only the memory contents betray it.
vol -f compromised.vmem windows.malfind --pid
| Injection tell | What it means |
|---|---|
| RWX private memory | Executable + writable + not file-backed; classic injected-code signature. |
| MZ header in private memory | A PE file mapped into a region that should not hold one; reflective load. |
| Hollowed process | A legitimate process whose image was replaced; pslist looks normal, the memory does not. |
| Unexpected executable region | An Office app or browser with executable private pages is worth investigating. |
Credential theft
LSASS holds the credentials of logged-on users in memory, which is exactly why it is the most-targeted process on a Windows host: dump LSASS and you walk away with hashes and sometimes plaintext for everyone logged on. Memory forensics works the other side of that attack. windows.hashdump, windows.lsadump, and windows.cachedump recover the credential material from the image, so you can establish exactly what an attacker who dumped LSASS would have obtained, scope which accounts must be considered compromised, and, by checking for injection or suspicious handles into LSASS, confirm whether the dump actually happened. The accounts you recover here define the blast radius of the incident.
vol -f image.raw windows.hashdump
| Plugin | Recovers |
|---|---|
| windows.hashdump | Local account NTLM hashes from the SAM. |
| windows.lsadump | LSA secrets, service-account credentials, cached material. |
| windows.cachedump | Cached domain credentials (logon for offline use). |
| windows.malfind on lsass | Injection into LSASS itself, a credential-theft tooling signature. |
Fileless malware and network
Fileless malware never writes its payload to disk: it runs from a script engine, a reflective load, or living-off-the-land tooling, so disk forensics finds nothing and memory is the only witness. The investigation chains process to network: find the script-engine or LOLBin process, read its command line, then map its connections. windows.netscan recovers the network connections from memory, including those the live tools were tricked into hiding.
# Find the script engine process
vol -f image.raw windows.pslist | grep -i powershell
# Recover the delivery command line
vol -f image.raw windows.cmdline --pid
# Detect the reflectively loaded payload
vol -f image.raw windows.malfind --pid
# Confirm payload absent from module list
vol -f image.raw windows.dlllist --pid
# Identify C2 connection
vol -f image.raw windows.netscan | grep
| Plugin | For |
|---|---|
| windows.netscan | Network connections and sockets from memory; the C2 channel. |
| windows.cmdline | The script-engine or LOLBin command line carrying the payload. |
| windows.dlllist | Loaded modules per process; suspicious or unsigned DLLs. |
| windows.dumpfiles | Carve a file or module out of memory for static analysis. |
Persistence and kernel rootkits
Persistence and kernel compromise are where memory forensics goes deepest. Registry hives are in memory too, so windows.registry.printkey reads autostart keys from the image. Kernel rootkits, the hardest threat to find anywhere else, are found by examining the structures they tamper with: windows.callbacks, windows.modules and windows.driverscan, and the interrupt tables. A driver in driverscan but not in the loaded-modules list is hidden, the kernel-level equivalent of the hidden process.
vol -f mf6-post-driver.raw windows.callbacks | head -20
| Plugin | Finds |
|---|---|
| windows.registry.printkey | Autostart and persistence keys, read from the in-memory hive. |
| windows.callbacks | Registered kernel callbacks; rootkits hook here to gain control. |
| windows.modules / driverscan | Loaded vs scanned drivers; the difference is a hidden driver. |
| windows.ssdt / idt | System call and interrupt tables; hooks indicate kernel tampering. |
Linux memory
Linux memory forensics follows the same logic with the linux.* plugins, and it matters most on exactly the hosts where disk forensics is hardest: long-running servers an attacker has had time to clean. Acquire with AVML (a static binary needing no kernel headers) or LiME, identify with linux.banner, then the familiar moves: process listing and scanning to find the unlinked process, syscall-table hook detection for the kernel rootkit, and bash-history recovery straight from RAM, which routinely survives a .bash_history the attacker wiped on disk. That last one alone has broken open investigations where every on-disk trace was gone.
vol -f linux-baseline.lime linux.banner
| Plugin | Reveals |
|---|---|
| linux.pslist / psscan | Processes from task structures vs scanned memory; the hidden-process diff. |
| linux.check_syscall | Hooked syscalls, the kernel-rootkit signature on Linux. |
| linux.bash | Shell history from RAM, recoverable when the disk history was wiped. |
| linux.malfind | Injected code regions in Linux process memory. |
An endpoint beacons to a known-bad IP, but the live tools and disk scan find nothing running. On the memory image, windows.psscan surfaces a process that windows.pslist does not, it was unlinked. windows.malfind against it shows an RWX private-memory region holding an MZ header: code reflectively loaded into a hollowed legitimate process. windows.netscan ties that process to the C2 connection.
Next: dump the region with windows.dumpfiles for static analysis and YARA, recover the command line and loaded modules, and use the findings to build host and network detections for the technique.
Quick lookup
| Hunting for | Volatility plugin |
|---|---|
| Hidden process | windows.psscan vs windows.pslist (diff them) |
| Code injection | windows.malfind (RWX private memory) |
| Credential theft | windows.hashdump / lsadump / cachedump |
| C2 / network | windows.netscan |
| What launched it | windows.cmdline, windows.pstree |
| Persistence | windows.registry.printkey |
| Kernel rootkit | windows.callbacks, windows.modules vs driverscan |
| Linux equivalents | linux.pslist/psscan, linux.check_syscall, linux.bash |
From running plugins to reading memory like an examiner
This cheatsheet is the plugin map. Applied Memory Forensics teaches the analysis: process injection, credential theft, fileless malware, persistence, kernel compromise, and Linux memory, each worked end to end against real images and correlated back to disk.
Explore the course