Skip to main content

Command Palette

Search for a command to run...

Windows Memory Forensics: Finding a Live Infection with Volatility

Tracing a live Windows infection through volatile memory, from a suspicious process to injected code, persistence, and attacker intent.

Updated
11 min readView as Markdown
Windows Memory Forensics: Finding a Live Infection with Volatility
R
Security engineer focused on AppSec, cloud security, and scaling enterprise security programmes in complex environments. I build and improve security capabilities across large-scale systems, with a focus on practical security engineering, visibility, and operational governance. My earlier work includes digital forensics and systems security, including OS internals and malware analysis, which continues to inform my approach to modern security problems.

PID 1484 had been running since boot. Nothing about that was unusual: it was Explorer.exe, the process every Windows machine on earth is running right now. What was unusual was the process hanging off it. Reader_sl.exe, launched at the exact same second, with an open TCP socket to a remote host that had no business talking to a legitimate Adobe helper application. The disk image alone couldn't tell you that. By the time you're imaging the drive, the socket is already closed and the process is already gone. The only place that connection still existed was in RAM.

This article walks through how that connection got found. Acquiring a Windows memory image correctly, then working through it with the Volatility Framework, plugin by plugin, in the order I actually ran them during a real investigation into a compromised host tied to a larger data-breach case.

A note on tooling. This investigation was run on Volatility 2.6, the version that taught a lot of us this discipline, against a static --profile and a target that was already an old OS at the time. Volatility 2 is now legacy: development has effectively frozen in favour of Volatility 3, which replaced static profiles with automatic symbol-table detection and is what you should reach for on a live case today. The investigative logic below hasn't changed at all; only the commands have. A comparison table is included at the end for anyone working from a current toolset.


Why Acquire Memory At All

Digital forensics generally follows an order of volatility: capture the most fragile data first, because every step after it risks destroying what came before. Registers and cache go first, then the ARP and routing tables, then running processes, then memory itself, and only after all of that does a disk image get taken. Memory sits near the top of that order for good reason. Registry hives, process handles, open network connections, decrypted strings, and injected payloads can all be recovered from a memory dump, and a meaningful amount of that evidence simply isn't recoverable from disk at all.

The trade-off is that acquiring memory is inherently invasive. There is no way to read RAM without the acquisition tool itself occupying some of it, so a memory dump is never a perfectly untouched artefact the way a write-blocked disk image can be. A pristine capture doesn't exist. The realistic goal is a documented, minimally invasive, repeatable one.


Acquisition: DumpIt

For the Windows host, acquisition was done with DumpIt, a single-binary tool that writes a raw physical memory image to disk with a minimal footprint. Run it, point it at write-accessible external storage rather than the host's own disk to avoid overwriting evidence, and it produces a raw image Volatility can ingest directly.

DumpIt writing a raw memory image out to external storage

Tooling note: this is the original 2011-era MoonSols/Comae build. That project has since been acquired by Magnet Forensics (2022) and is now free as Magnet DumpIt for Windows, still a fast, single-binary tool, but it now defaults to full Microsoft crash dumps rather than a raw image, and adds ARM64 support.


Working the Dump: The Volatility Workflow

Once the raw image exists, the Volatility Framework does the actual analytical work, walking the same kernel data structures the live OS would use, except offline and after the fact. What follows is roughly the order I run plugins in on a new case.

1. imageinfo: Establish What You're Looking At

Before anything else, imageinfo identifies the OS, service pack, and architecture the dump came from. Every other plugin needs a matching --profile argument. Get this wrong and everything downstream either fails outright or, worse, returns output that looks plausible but isn't.

imageinfo confirming the profile before any further plugins are run.

2. pstree: Map the Process Tree

pstree lists every running process at capture time, arranged by parent-child relationship. This is usually where the first anomaly surfaces. Every legitimate process has a PPID that traces back through a sensible lineage. Here, pstree showed Reader_sl.exe (PID 1640) with a PPID matching Explorer.exe (PID 1484), both started at the same timestamp. Adobe's helper process spawning as a child of Explorer.exe rather than the Reader application itself was the first red flag, well before any deeper analysis.

reader_sl.exe (PID 1640) sitting under explorer.exe (PID 1484) in the process tree, the first anomaly.

3. psxview: Find What's Hiding

psxview cross-references several independent internal process-listing mechanisms against each other: the standard linked list Windows uses, plus lower-level structures a rootkit would need to tamper with separately to stay fully hidden. If a process shows up in one listing but not another, commonly False under the pslist or psscan columns, that's a strong sign of active process hiding, something pstree alone can't surface, since it only reflects what the OS's own process list reports. In this case, psxview came back clean. No hidden processes. That's a useful negative result on its own, since it meant the malware wasn't relying on classic DKOM-style process hiding, which narrowed where to look next.

psxview confirming no processes were hidden from standard enumeration.

4. connscan and sockscan: Network State From Memory

connscan recovers TCP connections directly from kernel structures in memory, rather than relying on a live netstat that malware could have hooked or lied to. This is one of memory forensics' clearest advantages over disk analysis. A connection closed twenty minutes before acquisition isn't recoverable from disk at all, but its structures can still be sitting in memory. Here, connscan surfaced two outbound TCP connections from PID 1484, one to 41.168.5.140 and one to 125.19.103.198. The first of these turned out to be the malware's command-and-control server.

connscan recovering two outbound connections tied to PID 1484.

sockscan recovers open sockets more broadly and confirmed an active socket tied to the same PID that had already raised suspicion.

sockscan output. PID 1484's open socket stands out against the surrounding system noise.

5. cmdline: Recover Process Paths

cmdline extracts each running process's full invocation path. This is where "a process called Reader_sl.exe" becomes "a process launched from C:\Program Files\Adobe\Reader 9.0\Reader\Reader_sl.exe," confirming it sits in a legitimate install path. That deepens the suspicion rather than resolving it. It means the malware achieved persistence and camouflage by injecting into a genuine, correctly-located Adobe binary, rather than dropping an obviously foreign executable that endpoint tools would flag on sight.

cmdline confirming reader_sl.exe was running from its legitimate install path: camouflage, not a dropped foreign binary.

6. malfind: Detect Injected Code

malfind scans process memory for regions with suspicious characteristics, most commonly pages marked executable that don't map back to any file on disk, which is exactly what code injection produces. Here, malfind flagged both Explorer.exe and Reader_sl.exe as containing injected content. Combined with the process tree anomaly and the C2 connection, that gave a coherent picture: a legitimate binary used as a host process for injected code, a persistence and evasion technique chosen specifically because AV engines are far less likely to flag a well-known signed application.

malfind flagging an executable memory region inside explorer.exe with no backing file on disk, a strong indicator of code injection.

7. hivelist and Registry Analysis From Memory

hivelist prints the registry hives available directly from the memory image. Worth doing because registry hives are constantly being modified during normal operation, so a disk-only registry copy can already be stale by the time imaging finishes. Pivoting from the process analysis into HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run showed the only recent modification was a value pointing to KB00207877.exe. That filename also turned up inside Reader_sl.exe's recovered process memory as a prior-stage artefact, tying the registry persistence mechanism directly back to the same infection chain.

hivelist enumerating the registry hives recoverable from the live memory image.

8. procdump / memdump and Strings

procdump extracts a specific process's executable image back out of the memory dump for standalone analysis, and memdump extracts its full addressable memory space. Running strings against a memdump output is deliberately low-tech but consistently high-yield.

procdump and memdump pulling reader_sl.exe's image and full addressable memory out of the dump for offline analysis.

That strings pass surfaced the literal HTTP POST request the malware was using to beacon out to its C2 host.

strings against the process memdump surfacing the raw HTTP POST beacon to 41.168.5.140.

It also surfaced something more telling than the network indicators alone: a hardcoded list of banking domains sitting inside what was supposedly an Adobe reader helper.

A hardcoded target list of banking domains recovered from reader_sl.exe's memory, establishing intent rather than just infection.

That single artefact did more to establish attacker intent, targeted financial credential and card-data harvesting, than anything from the structured plugin output on its own.


What This Case Illustrates

None of the individual plugins here proved compromise on their own. pstree gave a lineage anomaly. psxview ruled out one entire class of hiding technique. connscan and sockscan gave a live network indicator that disk forensics could never have reconstructed. malfind gave the injection confirmation. hivelist tied it to a persistence mechanism. And a plain-text strings pass over a memdump output gave the clearest evidence of intent in the entire investigation. The value was in the combination, run in an order where each result narrowed where the next plugin needed to look.


Command Comparison: Volatility 2 (Then) vs Volatility 3 (Now)

Every plugin used above still exists in concept in Volatility 3. The questions they answer haven't changed, only the naming and the fact that you no longer hand-select a profile.

What you're checking Volatility 2.6 (used in this case) Volatility 3 (current)
Identify OS / profile imageinfo, then manually pass --profile=WinXPSP2x86 to every plugin No manual step. Symbol tables auto-detect the OS from the image
Process tree pstree windows.pstree
Hidden process check psxview windows.psxview
Network connections connscan / sockscan windows.netscan / windows.netstat
Process command line / path cmdline windows.cmdline
Injected code detection malfind windows.malfind
Registry hives hivelist windows.registry.hivelist
Process / memory dump procdump / memdump windows.dumpfiles (file-backed objects) and windows.memmap --dump (process memory)

The practical difference in a live investigation is smaller than the table suggests. You'd run vol3 -f memory.raw windows.pstree instead of volatility -f memory.raw --profile=WinXPSP2x86 pstree, get output in the same shape, and read it exactly the same way. The profile step disappearing is the single biggest quality-of-life change: no more guessing or mis-identifying a profile and quietly poisoning every plugin that follows it.


Key Takeaways for Practitioners

  • Acquire memory before disk wherever the order of volatility allows it. RAM state, once lost, is generally unrecoverable, while a disk image can usually still be taken later.

  • Run imageinfo first, every time. An incorrect profile silently degrades every plugin that follows it.

  • Treat pstree and psxview as complementary, not redundant. One shows the process tree as the OS reports it; the other tells you whether that report has been tampered with.

  • connscan and sockscan recover connection state that disk forensics cannot reconstruct at all. This is memory analysis's single clearest advantage over dead-disk analysis.

  • A legitimate install path from cmdline is not exoneration. Injecting into a correctly-located, signed binary is a deliberate evasion choice, not a coincidence.

  • Don't stop at the structured plugin output. Running strings against a raw process dump remains one of the highest-yield, lowest-effort steps in the entire workflow. It's what surfaced both the C2 beacon and the actual target list here.

This article is drawn from a digital forensics investigation into a Windows host compromised as part of a larger data-breach case, using DumpIt for acquisition and the Volatility Framework 2.6 for analysis.

The Forensic Trail

Part 2 of 2

The Forensic Trail is a practical digital forensics series exploring how systems store, hide, change, and leave behind digital evidence. From memory and disk artefacts to timestamps, file systems, boot records, and the techniques used to conceal data, each article examines the structures investigators rely on and how separate pieces of evidence can be analysed and connected to reconstruct what really happened.

Start from the beginning

GNU/Linux Memory Forensics: Is the Compromise Still Live?

Following the evidence in memory to determine what survived after an attack