Skip to main content
  1. Posts/

Memory forensics: what the blue team sees in your RAM

··1639 words·8 mins·
Table of Contents
This post is written from the operator side: what an incident responder will see in a memory image of a host you’ve established a foothold on, so you can design tradecraft that survives the analysis. Use on engagements within your rules of engagement. The techniques are also useful on the blue-team side, where understanding the operator perspective makes it easier to spot what they’re trying to hide.

Disk forensics catches the operators who left obvious artifacts behind. Once you start writing tradecraft that stays in memory and never touches disk, the discipline that catches you is memory forensics. Disk encryption protects data at rest, but the moment a user logs in, the keys live in RAM along with everything the operator put there: process structures, network connections, decrypted credentials, beacon shellcode, the command line that started the implant. An incident responder with a memory image and Volatility can reconstruct most of what an intrusion did during the last few minutes the machine was running, so an operator who wants to stay out of the report has to think about that image before the implant lands.

The tool
#

Volatility is the standard framework for extracting artifacts from raw memory dumps (.mem, .dmp, .vmss, hibernation files, VMware snapshots). The 2.x branch was archived in favor of Volatility 3, which is on the 2.28.x line as of mid-2026. Vol2’s plugin library was huge and a few niche techniques haven’t been ported, but for everything an operator needs to think about, Vol3 is the right tool to install.

Volatility usually gets paired with MemProcFS by Ulf Frisk, which takes a different approach. It mounts a memory image as a virtual filesystem, so interactive triage becomes a matter of cd and cat against the structured contents of the image. On a 32 GB dump, MemProcFS is often noticeably faster than Volatility for the same query, and most analysts I know reach for both during a real investigation.

A basic Vol3 invocation:

python3 vol.py -f memory.dmp windows.info

The windows.info plugin identifies the image, dumps the Windows build, and tells you whether the profile matches anything Volatility knows. From there, the analyst runs the hunt plugins.

What the hunt plugins find
#

Process list discrepancies
#

The defender runs two plugins side by side:

  • windows.pslist walks the kernel’s doubly-linked list of EPROCESS structures. This is the same view Task Manager shows.
  • windows.psscan carves the memory image for EPROCESS pool tags directly, regardless of what the linked list says.

A clean image returns identical process sets from both. A discrepancy means someone unlinked an EPROCESS block from the linked list to hide a process from pslist, leaving the actual structure in memory for psscan to find. That’s classic Direct Kernel Object Manipulation, and on default-configured modern Windows it does not work the way the 2010-era tutorials describe.

PatchGuard, HVCI (Hypervisor-protected Code Integrity), and Code Integrity policies have made unsigned kernel modification impractical on Win11 and Server 2022/2025 with the default security baseline. Operators who still need kernel access pivot to BYOVD (Bring Your Own Vulnerable Driver), loading a legitimately signed but exploitable driver. That move is itself loud: signed-driver loads from outside System32, especially of drivers on Microsoft’s vulnerable-driver blocklist, are exactly what EDR is watching for.

The tradecraft that actually works against pslist/psscan discrepancy detection takes the opposite tack: instead of hiding a process, inject into one that already belongs there. The EPROCESS for notepad.exe is going to be present in both lists, exactly as Windows expects it to be, and what an operator cares about is what’s living inside that process’s address space.

Floating executable code (malfind)
#

windows.malfind looks for memory pages that are executable, not backed by a file on disk, and that start with bytes that look like x86/x64 instructions. The default RWX shellcode loader (allocate with VirtualAlloc(... PAGE_EXECUTE_READWRITE), copy shellcode, jump) creates exactly that signature.

Two operator responses:

Module stomping loads a legitimate signed DLL into the target process via LoadLibrary, then overwrites the contents of its .text section with shellcode. The page protections stay as RX (read-execute, file-backed), so malfind sees a normal-looking region backed by a real file. The catch is that the DLL on disk now does not match the bytes in memory, and any plugin that compares loaded DLL contents against the disk version (Volatility’s windows.dlllist plus a manual diff, or MemProcFS’s integrity checks) flags it. Module stomping is a fingerprint visible to mature memory forensics; it’s just a different fingerprint than the RWX one.

Phantom DLL hollowing is a different technique despite the similar name. It uses NtCreateSection against a real DLL on disk via the transactional NTFS API (or section mapping), gets a section handle that the kernel believes is backed by the original file, then writes the operator’s payload through the section before the integrity machinery has a reason to recheck. The page comes out RX, file-backed by name, and the contents do not match the disk file. The forensic signature is subtler than module stomping but still detectable in 2026 with the right plugin.

The newer move is sleep masking, which sidesteps malfind by making sure the shellcode isn’t in an executable state when the snapshot gets taken. Ekko (CreateTimerQueueTimer with NtContinue context-switch tricks), FOLIAGE (APC-based), and Cobalt Strike’s Sleep Mask Kit all do variants of the same thing: during the beacon’s idle period, flip the shellcode region from RX to RW, encrypt the contents in place, then flip back to RX and decrypt on wake. A memory snapshot taken during the sleep window finds an encrypted blob with no obvious instruction bytes. malfind’s “starts with assembly-looking bytes” heuristic doesn’t fire.

Network connections
#

windows.netscan enumerates active TCP and UDP endpoints. The classics that get flagged:

  • A powershell.exe connection to port 4444 on a non-corporate IP. The default Metasploit port is on every analyst’s reflex list.
  • A svchost.exe listening on a random ephemeral port, when svchost.exe should be hosting one of the well-known service categories on a documented port.
  • A beacon connection to a domain that resolves to a residential ASN or a recently registered domain. Network context matters as much as the connection itself.

The tradecraft response lives in the C2 channel design rather than in the memory artifacts. The connection is going to exist in netscan output either way; what matters is whether an analyst looking at it sees something that fits the host’s normal outbound traffic profile or something that immediately reads as foreign.

Command line history (windows.cmdline)
#

windows.cmdline recovers the command lines used to launch processes. Loud examples:

  • powershell.exe -enc <long base64 blob>
  • mimikatz.exe "sekurlsa::logonpasswords" exit
  • rundll32.exe \\share\evil.dll,EntryPoint

The classic operator response was PEB argument spoofing: launch the process with a benign command line, suspend it before it runs, walk the PEB to replace the CommandLine in the RTL_USER_PROCESS_PARAMETERS structure with the real payload, then resume. Volatility reading the PEB gets the benign version.

That technique works against userland-only telemetry. It does not work against modern endpoint visibility, because Sysmon EID 1 and most EDR kernel callbacks capture the true command line at process creation time via the PsSetCreateProcessNotifyRoutineEx callback, before the PEB ever gets rewritten. The argument spoof shows up as a delta between what the EDR logged at creation and what Volatility reconstructs from the PEB later, which is itself an indicator. The technique still has a place against environments without EDR or with the process-creation callback misconfigured, but treating it as a general-purpose obscurer hasn’t been a reasonable default for a while.

Credentials
#

Memory forensics has historically been the easiest way to dump credentials that aren’t sitting on disk, and the picture in 2026 is meaningfully different from what it was even a few years ago.

windows.hashdump.Hashdump recovers NTLM hashes from the SAM in a memory image. windows.lsadump.Lsadump (note: not lidadump, which is a typo that has propagated through some older blog posts) extracts LSA secrets. Both still work against unprotected systems and against the SAM hashes on any Windows host.

What’s changed: Credential Guard has been default-on for new Windows 11 installations since 22H2 (eligible hardware, domain-joined or AAD-joined) and on Server 2025 by default. It runs LSA secrets in a VBS (Virtualization-Based Security) isolated container that isn’t readable from the normal LSA process, which means Mimikatz-style memory extraction of NTLM hashes and Kerberos TGTs against modern hosts mostly returns nothing useful. Local SAM hashes and non-VBS-protected secrets are still in scope, but the post-2022 picture is much less Mimikatz-friendly than the post-2016 one.

The cheap-and-cheerful credential extraction technique that still works almost everywhere:

strings memory.dmp | grep -iE "password|passwd|pwd" | less

Users type passwords into browser forms, RDP prompts, and VPN clients. The buffers linger in RAM long after the credential has been submitted. On a memory image from a workstation that’s been up for a day, this grep is depressing in its hit rate.

Self-checking your own tradecraft
#

The fastest way to know what an incident responder will see on a host you’ve compromised is to take a memory image of your own test VM after running your loader, and dump it through Volatility yourself. If your beacon shows up in pslist/psscan, in malfind, in netscan resolving to a default Metasploit port, or in windows.cmdline as obvious base64, the IR team will find it on day one of the engagement followup, and finding that out in the lab is materially cheaper than finding it out in the followup email.

The defender side of the same operator’s job is the inverse exercise: take a memory image of a suspicious host in your environment, run the plugins this post describes, and look for the signatures your red team taught you to spot. The Volatility and MemProcFS installs are identical to the ones the operator was using on the other side of the engagement. The change of seat doesn’t change the artifacts.

UncleSp1d3r
Author
UncleSp1d3r
As a computer security professional, I’m passionate about building secure systems and exploring new technologies to enhance threat detection and response capabilities. My experience with Rails development has enabled me to create efficient and scalable web applications. At the same time, my passion for learning Rust has allowed me to develop more secure and high-performance software. I’m also interested in Nim and love creating custom security tools.