Memory is the one place where attackers cannot hide: whatever code is executing must be in RAM. A process can delete its binary from disk, overwrite its registry key, and clear event logs — but as long as it’s running, its code, network connections, and module list are in memory. Memory forensics is the hunter’s truth oracle.
Memory Analysis Workflow
Memory Image (raw dump or live memory)
│
▼ Step 1: Process enumeration
pslist + psscan (find all processes, catch DKOM)
│
▼ Step 2: Network state
netscan (active + recently closed connections)
│
▼ Step 3: Target suspicious PIDs
cmdline → what was the process started with?
dlllist → what DLLs are loaded?
ldrmodules → any unlinked modules (reflective injection)?
│
▼ Step 4: Injection detection
malfind → executable private memory (shellcode / injected code)
│
▼ Step 5: Extract artifacts
procdump → dump executable from memory
dumpfiles → dump open file handles
hashdump → extract NTLM hashes (if credential dump suspected)
Core Volatility 3 Commands
Process Enumeration
# List processes via EPROCESS linked list
vol.py -f memory.raw windows.pslist.PsList
# Scan for EPROCESS pool tags (catches DKOM-hidden procs)
vol.py -f memory.raw windows.psscan.PsScan
# Process tree with parent-child visualization
vol.py -f memory.raw windows.pstree.PsTree
# Command lines of all processes
vol.py -f memory.raw windows.cmdline.CmdLine
What to look for:
pslist output:
PID PPID Name Offset Threads Handles SessionId
3872 644 svchost.exe 0xe0018340 12 423 0
8844 3444 svchost.exe 0xe0054a80 6 89 1 ← PPID 3444 = powershell.exe (not services.exe)
Anomaly: svchost.exe with PPID pointing to powershell.exe = injection target
Network State
# Active and recently terminated connections
vol.py -f memory.raw windows.netscan.NetScan
# Output includes: Proto, LocalAddr:Port, ForeignAddr:Port, State, PID, Owner
Proto Local Foreign State PID Owner
TCPv4 10.1.2.33:50111 185.220.101.9:443 ESTABLISHED 8844 svchost.exe
A svchost.exe PID making outbound ESTABLISHED connections to external IPs is a finding — legitimate svchost instances don’t establish outbound TCP to external hosts.
Injection Detection
# Find executable private memory (shellcode / injected PE)
vol.py -f memory.raw windows.malfind.Malfind
# Limit to specific process for speed
vol.py -f memory.raw windows.malfind.Malfind --pid 8844
Process: svchost.exe PID: 8844 Address: 0x1a0000
Vad Tag: VadS
Protection: PAGE_EXECUTE_READWRITE
Flags: CommitCharge: 24, PrivateMemory: 1, Protection: 6
4d 5a 90 00 03 00 00 00 MZ...... ← PE header in private memory
04 00 00 00 ff ff 00 00 ........
MZ header in a private (non-file-backed), executable region of svchost.exe = injected PE (reflective DLL or process hollowing). This is the highest-confidence injection indicator.
Module Analysis
# DLLs loaded by a process (via PEB)
vol.py -f memory.raw windows.dlllist.DllList --pid 8844
# Compare PEB lists vs VAD tree (catch reflective injection)
vol.py -f memory.raw windows.ldrmodules.LdrModules --pid 8844
ldrmodules output to look for:
Pid Process Base InLoad InMem InInit MappedPath
8844 svchost.exe 0x7ffd1a000000 True True True C:\Windows\System32\ntdll.dll
8844 svchost.exe 0x1a0000 False False False (no mapped file) ← INJECTED
A memory region at 0x1a0000 with False/False/False in all three PEB lists but present in the VAD tree as executable = not loaded via the Windows loader = reflective injection.
Artifact Extraction
# Dump an executable from memory (use when binary deleted from disk)
vol.py -f memory.raw windows.procdump.ProcDump --pid 8844
# Extract from malfind region (dump the injected code)
vol.py -f memory.raw windows.dumpfiles.DumpFiles --pid 8844 --virtaddr 0x1a0000
# Credential hash extraction
vol.py -f memory.raw windows.hashdump.Hashdump
MemProcFS: Rapid Triage
When you don’t know which PID to target yet, MemProcFS provides instant browsable access to the full memory image:
# Mount the memory image as a filesystem
./memprocfs -device memory.raw -mount /mnt/mem
# Browse like a normal filesystem
ls /mnt/mem/proc/
# → [pid_list]
ls /mnt/mem/proc/8844_svchost.exe/
# → cmdline.txt dlls/ files/ handles/ net/ pe/ threads/
cat /mnt/mem/proc/8844_svchost.exe/cmdline.txt
# → C:\Windows\system32\svchost.exe -k netsvcs
cat /mnt/mem/proc/8844_svchost.exe/net/netconn.txt
# → TCP 10.1.2.33:50111 → 185.220.101.9:443 ESTABLISHED
ls /mnt/mem/proc/8844_svchost.exe/dlls/
# → ntdll.dll kernel32.dll ... [injected.dll is NOT here — reflective injection]
MemProcFS forensic timeline (all processes combined):
cat /mnt/mem/forensic/timeline.csv | sort -t, -k1 | head -50
# TimeGenerated, Type, PID, Process, Info
# 2024-09-02 14:23:44, Net, 8844, svchost.exe, ESTABLISHED 185.220.101.9:443
# 2024-09-02 14:23:11, Proc, 3444, powershell.exe, Created
# 2024-09-02 14:21:07, Proc, 2188, cmd.exe, Created