strings is the first move, not the last
The picoCTF 2025 Bitlocker-2 writeup I keep linking to has one command in its solve block: strings memdump.mem | grep picoCTF. That is the entire answer. A BitLocker drive was mounted when someone captured RAM, the decrypted flag sat in memory as printable bytes, and grepfinds it in eight seconds. It's the cleanest memory-forensics solve on the site. It's also a trap, because every picoCTF player who sees it walks away thinking memory forensics is strings plus patience.
After cataloguing the Forensics category across every picoCTF edition on this site, I can tell you what the RAM-dump corner actually contains: Bitlocker-2. That is the list. One challenge, solvable with the same one-liner that solves most steganography puzzles. Which is fine, until the organisers eventually ship a problem where the flag isn't sitting in printable bytes and you need a tool that can reconstruct the state the machine was in when the snapshot was taken.
That tool is Volatility 3. It takes a raw memory snapshot and parses it back into the kernel data structures a live machine would have in RAM: process lists, open files, network connections, loaded drivers, page tables. Once parsed, you query those structures as if the machine were still running. You have solved a few forensics challenges with file, binwalk, and strings. You have never opened Volatility. By the end of this post you'll know the five plugins that matter for CTF-scale dumps, in the order the evidence sends you, not the order the docs list them.
Install once, skip the profile fight
Volatility 3 is the version to install in 2026. Not Volatility 2. The v3 release is worth teaching because it makes the biggest beginner pitfall disappear, which is having to guess a Windows profile before any plugin will run. The current stable is v2.27.0 (released 2026-01-29, confusingly numbered because the framework version and the Volatility version diverged a while back).
pip install volatility3vol --help
The CLI is vol (or vol.py if you cloned from source). Point it at a dump and ask it the first question any investigator asks:
vol -f memdump.mem windows.info
The first time v3 sees a Windows dump, it looks at kernel signatures, fetches the matching ISF (Intermediate Symbol Format) table from the Volatility Foundation CDN, caches it, and prints the OS version and build. In Volatility 2 you used to guess --profile=Win10x64_19041 and watch errors until you guessed the right one. Not anymore.
What actually changed from v2
Three things matter when you read an old cheat sheet and nothing matches:
- No profiles. v3 identifies the OS from the dump itself.
- Plugins are namespaced. The old
pslistis nowwindows.pslist. Every old-syntax plugin in a SANS cheat sheet gets awindows.prefix. - Output goes through a renderer. Default is a column-aligned table (the framework calls it a TreeGrid internally). Pass
-r csvor-r jsonwhen you want to grep or post-process.
The four-question ladder
Volatility 3 ships dozens of plugins. You don't need them.
For a CTF-scale dump, five plugins run in the right order will crack almost every memory challenge you see. The order isn't alphabetical and it isn't what the plugin listing gives you. It's the order that answers four questions about the machine:
- What was running?
windows.pslist(pluswindows.pstreefor the parent-child view). - What did it talk to?
windows.netscan. - What did it touch?
windows.cmdline,windows.filescan,windows.handles. - What did it hide?
windows.malfind,windows.registry.hivelist, and the third-partywindows.bitlockerplugin when encryption is in play.
One question, mostly one plugin. If the brief hints at a user typing commands when the dump was captured, skip to cmdline. If the scenario mentions malware, malfindis where the flag lives. Let the brief tell you where to start, and let each plugin's output send you to the next.
The decision tree
The ladder tells you which questions to ask. This is the shape of answering them. Every Volatility tutorial I've read publishes a linear plugin list. SANS publishes a six-phase methodology; HackTricks publishes an unordered menu; Varonis publishes a workflow. None of them publish an if-then tree where the output of one plugin routes you to the next. For CTF triage that's exactly the shape you need.
windows.pslistfirst. If a process has a weird image path, no parent process ID (PPID), or a name that doesn't belong, follow the left column to investigate that process in depth. If everything looks like a stock machine that happened to have Outlook and Chrome open, follow the right column to look at connections, files, and registry. The DumpMe walkthrough below actually crosses the two columns: it starts right (netscan surfaces the suspect), then jumps left (pstree and malfind on that PID). Real investigations do this.The part tutorials skip: you'll dead-end. Not every branch finds a flag. Some dumps were captured minutes before the interesting thing happened, and every plugin returns clean output. That's when you loop back to the challenge brief, which you've now read three times and which probably contains the hint you need.
Walkthrough: Bitlocker-2, two ways
The site page for Bitlocker-2 shows the intended solve. Here is that solve, then here is what Volatility 3 would have told you instead.
The strings solve (eight seconds)
gunzip memdump.mem.gzstrings memdump.mem | grep picoCTF# picoCTF{B1tl0ck3r_dr1v3_d3crypt3d_902...}
Flag submitted. Challenge solved. This works because BitLocker was mounted when the RAM capture happened, Windows keeps plaintext of recently-accessed files in its page cache, and stringsscans every printable byte in the dump. If the flag was inside a file on the encrypted volume and someone had read that file in the minutes before capture, it's sitting in cache as ASCII.
The Volatility path (five minutes, and you learn something)
The reason to run Volatility on the same dump is to recover the FVEK (Full Volume Encryption Key), the actual AES key BitLocker holds in RAM while the volume is mounted. Once you have it, you can decrypt the disk image independent of the user password.
Mainline Volatility 3 doesn't ship a BitLocker plugin. There's a community port at github.com/lorelyai/volatility3-bitlocker. Clone it, point v3 at it through --plugin-dirs:
git clone https://github.com/lorelyai/volatility3-bitlockervol -f memdump.mem -vvv \--plugin-dirs ./volatility3-bitlocker \windows.bitlocker.BitlockerFVEKScan \--tags FVEc Cngb None --dislocker# writes one or more 0x<addr>-Dislocker.fvek files in the cwd
The plugin may emit more than one FVEK candidate (one per plausible key address it finds). Pick the first one, or try each in turn. Now mount the disk image with dislocker using the uppercase -K flag, which is the FVEK flag (lowercase -k is for BEK (BitLocker External Key) recovery files and will silently fail on an FVEK):
sudo dislocker -V bitlocker-2.dd -K ./0x<addr>-Dislocker.fvek -- /mnt/dislockersudo mount -t ntfs-3g /mnt/dislocker/dislocker-file /mnt/decryptedls /mnt/decrypted/
The volume is mountable without knowing the password. Everything Jacky had on that drive is now browsable. The flag is one of the files, yes, but so is everything else.
strings retrieves a flag. Volatility reconstructs the state of a machine. Those are different jobs.--profile flag. No shame in mixing.The deeper point isn't that Volatility was necessary for Bitlocker-2. It wasn't. The point is that the plugins reconstruct the machine. When a future picoCTF dump hides the flag inside a file that was opened and closed before capture, strings will return gigabytes of unrelated text and the FVEK path will still work.
When Volatility is the only path
Bitlocker-2 is a shortcut case: the scenario announces itself (encrypted drive, unlocked at capture time), so you can skip the triage tree and reach straight for the plugin built for exactly this shape of problem. That is honest, and it is why Bitlocker-2 alone does not teach you the tree. For a case where the scenario does not announce itself and the plugins actually carry the investigation, the reference sample is CyberDefenders Lab 65 DumpMe. Free download with an account. The scenario: an employee's Windows 7 workstation got compromised with a Meterpreter payload (Meterpreter is Metasploit's interactive payload framework). You have the triage memory dump. Find the attacker's process, the C2 (command-and-control) connection, and the injected code.
Why stringsdies here: the payload isn't flag text, it's a Meterpreter session. The evidence you care about is the live C2 connection and the RWX (read-write-execute) anonymous memory region holding the staged PE. Neither of those shows up as printable ASCII you can grep. A strings pass on the whole dump returns thousands of hits for anything vaguely hostname-shaped, none of which tell you which process was talking or what it was running.
The three-plugin path (reproduced from DFIRHive's Volatility 3 walkthrough, October 2025):
# Q2: what did each process talk to?vol -f Triage-Memory.mem windows.netscan# ... PID 3496 TCP ... 10.0.0.106:4444 ESTABLISHED UWkpjFjDzM.exe
One process has an outbound connection on port 4444, which is Metasploit's default handler port. That alone makes PID 3496 the suspect. The process name closes it: UWkpjFjDzM.exe. Legitimate binaries on a Windows 7 workstation don't have randomized ten-character names, and a dropper that couldn't bother picking a convincing filename has been running long enough to hold an active C2 session.
# Q3a: what arguments was it invoked with?vol -f Triage-Memory.mem windows.cmdline | grep 3496# (empty)# Q3b: who spawned it?vol -f Triage-Memory.mem windows.pstree# hfs.exe (3952) -> wscript.exe (5116) -> UWkpjFjDzM.exe (3496) -> cmd.exe (4660)
cmdline for 3496 comes back empty, which for a running process is already a signal: benign binaries almost always have arguments or at least a path. The parent chain is what pstree draws, and the shape it draws is unambiguous. HFS (an HTTP file server) was handing a script to wscript.exe, wscript executed the script, the script dropped and ran the random-named binary, and the binary spawnedcmd.exe for whoever was on the other end of the C2 session. That is the Metasploit delivery shape: loader, dropper, shell.
# Q4: what did it hide?vol -f Triage-Memory.mem windows.malfind --pid 3496# RWX anonymous regions with MZ headers = injected PE
Shellcode found. MZ is the magic bytes of a Windows PE (Portable Executable); seeing them inside an anonymous RWX region means someone dropped a full executable image into memory that was never loaded from disk in the normal way. Dump the suspicious regions for offline analysis (pass --dump tomalfind itself; it writes one file per flagged region):
vol -f Triage-Memory.mem windows.malfind --pid 3496 --dump
Notice the sequence. From pslist alone, nothing obviously wrong. From strings, nothing either. It's netscan surfacing the suspect, pstree and cmdline drawing the parent chain, then malfind confirming the injected code, in that order, that tells the story. If a future picoCTF memory challenge ever looks like this, you now have the path through it.
Alternatives and escape hatches
A few honest caveats and follow-ups for when Volatility 3 isn't the right tool or when it breaks on your specific dump.
Volatility 2 is still relevant
Old plugins never got ported. The community breppo/Volatility-BitLocker for v2 has broader compatibility than its v3 successor. Same story for a handful of rootkit-specific and registry-specific plugins. Install v2 alongside v3. When the v3 plugin fails with a kernel-struct error, drop to v2 with --profile=Win10x64_19041(or whatever the dump's build dictates), run the old plugin, and go back to v3 for everything else.
MemProcFS for interactive work
MemProcFS (Ulf Frisk, current release v5.17 from February 2026) takes a different approach: it mounts the memory dump as a filesystem. You cd into /mnt/memprocfs/pid/3496/modules/ and every artefact is a file you can cat, grep, and diff. For CTFs with 10+ memory challenges and a tight clock, plugins are faster. For interactive exploration and learning what data even exists inside a memory dump, MemProcFS is genuinely nicer. Pick the one that matches the task.
Rekall is dead
Google archived Rekall in October 2020. Do not install Rekall in 2026. Older walkthroughs reference it; skip those sections.
Required reading
Halderman et al., 2008, Lest We Remember: Cold Boot Attacks on Encryption Keys. Alex Halderman and eight co-authors across Princeton, the EFF, and Wind River, USENIX Security 2008. The paper that showed RAM contents survive long enough after power-off that an attacker can chill the DIMMs with a compressed-air duster, pop them into a second machine, and read out encryption keys before they decay. That is the foundational insight of memory forensics as a discipline: if keys persist in RAM after power loss, they definitely persist in a dump taken while the system is running. Forty minutes of reading, and every memory-forensics tutorial since has been a footnote to it.
While you have the tool installed, solve Bitlocker-2 twice. Solve it with strings first because you can do it in eight seconds. Then install the v3 BitLocker plugin, extract the FVEK, mount the disk image with dislocker, and browse what Jacky had on that drive. The first solve gets you the flag. The second solve teaches you what memory forensics actually is.
When the next picoCTF memory dump drops and strings | grep picoCTFcomes back empty, that's not the end of the challenge. It's the start.
Quick reference
| Question | Plugin | One-line purpose |
|---|---|---|
| Where am I? | windows.info | OS version, build, kernel base |
| What ran? | windows.pslist | Active process list |
| Parent-child tree? | windows.pstree | Processes in a tree by PPID |
| What was it told to do? | windows.cmdline | Command-line args for each process |
| What libs did it load? | windows.dlllist | Loaded DLLs per process |
| What did it talk to? | windows.netscan | Network sockets and connections |
| What files did it open? | windows.filescan | File objects in kernel memory |
| Any injected code? | windows.malfind | RWX anonymous regions (shellcode) |
| Registry hives in memory? | windows.registry.hivelist | Offsets of loaded registry hives |
| Hashes and secrets? | windows.hashdump | SAM (Security Account Manager) hashes from memory |
| BitLocker volume? | windows.bitlocker (community) | FVEK extraction, pair with dislocker |
Related forensics on this site