Chapter 19

Memory Acquisition

A RAM image captured at the right moment contains the most complete picture of a live attack — decrypted C2 communications, injected shellcode, in-memory credentials, active network connections, and every running process. This chapter covers acquisition tools, formats, verification, and what you're capturing when you image memory.

Scenario

An alert fires: a process on a critical server is making outbound connections to an unusual IP on port 443. The EDR identifies it as potential Cobalt Strike beacon activity. The malware may be entirely in memory — no files on disk. If you reboot to avoid disruption, everything in RAM is gone. If you isolate via EDR first and then take a memory image, the network state is preserved but the active connections are closed. The right sequence: (1) take live process/network snapshot via a 2-minute script, (2) immediately acquire RAM image while the beacon is still running, (3) then isolate via EDR. The memory image captures the decrypted config, the C2 IP, and the injected code — evidence you can't get from disk forensics alone.

What's in RAM: The Forensic Goldmine

  Evidence Available Only in Memory
  ═══════════════════════════════════════════════════════════════════

  Processes and threads:
    ├── Every running process with its full in-memory image
    ├── Processes injected into (hollowed or injected code visible)
    ├── Terminated processes (may still have memory mapped)
    └── Process handles (what files/registry keys are open)

  Network state:
    ├── Active TCP connections with remote IPs
    ├── Listening ports
    ├── Recently closed connections (cached in TCB)
    └── Sockets and their associated process PIDs

  Credentials:
    ├── LSASS process memory: NTLM hashes, Kerberos tickets, cleartext (if WDigest enabled)
    ├── Browser credential caches
    ├── VPN/Wi-Fi saved credentials
    └── Application session tokens (cookies, JWTs) in process heap

  Decrypted content:
    ├── Malware config (C2 domains, encryption keys — decrypted at runtime)
    ├── Ransomware encryption keys (before files are encrypted)
    ├── Browser HTTPS session data (SSL/TLS keys stored in NSS3 structures)
    └── Any data the process decrypted to work with

  Injected code:
    ├── Shellcode injected into legitimate processes
    ├── Reflective DLL injections
    └── Process hollowing payloads (visible as PE in unexpected memory)

Acquisition Tools

ToolPlatformOutput formatNotes
WinPmemWindowsRaw or AFF4Open source, part of Velociraptor DFIR toolkit. Standalone EXE, no install. Most commonly used in professional IR.
Magnet RAM CaptureWindows.mem (raw)Free, GUI tool from Magnet Forensics. Good for field acquisition by non-technical first responders.
DumpIt (Comae)Windows.bin or .dmpMinimal UI — double-click and it images RAM. Renamed to Comae DumpIt. Raw output compatible with Volatility.
avmlLinuxLIME format or rawMicrosoft's open-source Linux memory acquisition tool. No kernel module required — works without LiME.
LiME (Linux Memory Extractor)LinuxLIME formatLoadable kernel module. Most reliable on Linux but requires kernel module loading. Gold standard for Linux memory forensics.
osxpmemmacOSAFF4 or rawmacOS memory acquisition. Kernel extension required (getting harder with SIP). macOS forensics is increasingly cloud-log-dependent.
PowerShellwinpmem-acquire.ps1
# WinPmem memory acquisition
# Run from USB or network share — don't write to the target system's disk

param(
    [string]$OutputDrive = "D:",
    [string]$CaseName   = "CASE001"
)

$hostname  = $env:COMPUTERNAME
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$outDir    = "$OutputDrive\evidence\$CaseName\$hostname"
$ramFile   = "$outDir\$hostname-RAM-$timestamp.raw"
$winpmem   = "D:\tools\winpmem_mini_x64_rc2.exe"

New-Item -ItemType Directory -Path $outDir -Force | Out-Null

# Pre-acquisition: capture volatile state FIRST
Write-Host "[*] Capturing live process list..."
Get-WmiObject Win32_Process |
    Select-Object ProcessId, Name, CommandLine, ParentProcessId |
    Export-Csv "$outDir\processes-live.csv" -NoTypeInformation

Write-Host "[*] Capturing network connections..."
netstat -anob 2>&1 | Out-File "$outDir\netstat-live.txt"

# RAM acquisition
Write-Host "[*] Starting RAM acquisition to $ramFile"
Write-Host "[*] Estimated time: $([Math]::Ceiling((Get-WmiObject Win32_ComputerSystem).TotalPhysicalMemory / 1GB * 3)) minutes"
$start = Get-Date

& $winpmem $ramFile

$elapsed = (Get-Date) - $start
Write-Host "[*] Acquisition complete in $($elapsed.TotalMinutes.ToString('0.0')) minutes"

# Hash verification
$hash = Get-FileHash -Path $ramFile -Algorithm SHA256
Write-Host "[*] SHA-256: $($hash.Hash)"
Write-Host "[*] Size: $('{0:N2}' -f ((Get-Item $ramFile).Length / 1GB)) GB"

# Record in chain of custody
[PSCustomObject]@{
    Timestamp   = (Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC")
    Investigator= $env:USERNAME
    Host        = $hostname
    Action      = "RAM acquisition"
    File        = $ramFile
    SHA256      = $hash.Hash
    SizeGB      = (Get-Item $ramFile).Length / 1GB
} | Export-Csv "$outDir\chain-of-custody.csv" -Append -NoTypeInformation

Linux Memory Acquisition

Bashlinux-memory-acquire.sh
# Linux memory acquisition with avml (no kernel module needed)
# Download: https://github.com/microsoft/avml/releases

# Install avml
curl -Lo /usr/local/bin/avml \
  https://github.com/microsoft/avml/releases/latest/download/avml
chmod +x /usr/local/bin/avml

# Acquire to evidence drive
HOSTNAME=$(hostname)
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
OUTPUT="/mnt/evidence/${HOSTNAME}-RAM-${TIMESTAMP}.lime"

avml $OUTPUT

# Hash and document
sha256sum $OUTPUT | tee "${OUTPUT}.sha256"

echo "Memory acquisition complete:"
echo "  File: $OUTPUT"
echo "  Size: $(du -sh $OUTPUT | cut -f1)"
echo "  Hash: $(cat ${OUTPUT}.sha256 | cut -d' ' -f1)"

# Alternative: LiME (requires kernel module)
# insmod lime-$(uname -r).ko "path=/mnt/evidence/mem.lime format=lime"
# The module cleans up on rmmod; format=raw also supported

Windows Crash Dumps as Memory Sources

Windows crash dumps (minidump, kernel dump, full dump) are memory images created automatically when the system encounters a BSOD. They can be analyzed with Volatility like any other memory image.

Dump typeLocationContentsForensic usefulness
Full memory dumpC:\Windows\MEMORY.DMPComplete physical RAM contentsEquivalent to WinPmem acquisition — contains everything
Kernel memory dumpC:\Windows\MEMORY.DMP (default)Kernel space only — not user spaceUseful for kernel-mode rootkit analysis; misses user-space credential stores
Automatic memory dumpC:\Windows\MEMORY.DMPKernel + minimal pages needed for analysisVaries — may miss critical user-space content
MinidumpC:\Windows\Minidump\*.dmpStack trace + very limited RAMNot useful for memory forensics — only for crash debugging

Q & A

Q: Can you analyze memory from a virtual machine without a WinPmem-style acquisition?

Yes — hypervisors provide memory acquisition mechanisms that often give better results than in-guest tools. For VMware: the .vmem file in the VM's directory on the host is a raw memory dump of the running VM — copy it (while the VM is suspended or with atomic snapshot) and analyze directly with Volatility. For VMware, also copy the .vmss (suspend state) file — Volatility has a VMware VMSS reader. For Hyper-V: use the CheckpointVM PowerShell command to create a checkpoint (includes memory state) then export the VMRS file. For VirtualBox: take a snapshot — the .sav file contains memory. For cloud VMs (AWS/Azure): check if the hypervisor supports memory capture via the management API before trying in-guest acquisition. In-guest acquisition tools like WinPmem work correctly inside VMs, but hypervisor-level capture is "outside looking in" and is less susceptible to rootkit interference with the acquisition process.