A memory analysis workflow that finds things
5 min read
A memory analysis is not a checklist. It is a workflow with five stages that feed each other: triage points at suspects, suspects open pivots, pivots set up deep analysis, deep analysis surfaces things carving corroborates, and everything lands in a report that ties claims to evidence. Skip a stage and you miss things. Run them in order and you catch what modern threats look like in 2026.
This version is built around ramparser for triage and Volatility 3 for depth. For the bird's-eye view of the discipline, read RAM forensics: tools, techniques, and a 2026 workflow. For the per-tool trade-offs see the memory forensics tools comparison.
Stage 1: Triage
The goal is one question: is anything obviously wrong? You are looking for smoke, not fire. The stage assumes you already have a memory image on disk; if not, the Magnet RAM Capture guide covers acquisition end-to-end.
Drop the image into ramparser. Within seconds:
- pslist — the live process tree from kernel
ActiveProcessLinks. - psscan — every
_EPROCESSobject the pool scanner finds. - psxview — the diff.
A row in
psscanmissing frompslistis the classic DKOM-hidden- process signature. - pstree — parent / child relationships.
Scan for:
- Unexpected names. A
svchost.exerunning fromC:\Users\…\AppDatainstead ofSystem32. Achrome.exewith no Chrome parent. - Mismatched parents.
cmd.exespawned bywinword.exe,powershell.exeparented to a service that has no business launching shells. - Hidden rows. Anything
HIDDENinpsxviewgets a star. - Suspicious counts. Five
lsass.exe. Threewininit.exe. There should be exactly one of each.
Triage's deliverable is a suspect list — typically 1 to 5 PIDs.
Stage 2: Pivot on suspects
Three pivots per suspect tell the story.
Command line (PEB)
cmdline reads the Process Environment Block and recovers the exact
command line. This is where you catch:
- Base64-encoded PowerShell.
- Suspicious flags (
-EncodedCommand,-WindowStyle Hidden,-NoProfile -ExecutionPolicy Bypass). - Paths to dropped binaries.
- Beacon configuration hints.
Loaded modules
dlllist shows every module loaded into the process. Look for:
- DLLs from
%TEMP%or unusual paths. - DLLs with names mimicking system ones (one-letter-off typosquats).
- Missing expected DLLs (a credential manager with no
samlib.dll).
Network endpoints
netscan ties the process to the outside world:
- Outbound to unusual ASNs or known C2 infrastructure.
- Local listeners on high ports.
- Established connections to addresses that do not fit the host's role.
When two of these three agree — a suspicious cmdline running from a strange path with an outbound to known-bad infrastructure — that is a real finding, not a hunch.
Stage 3: Deep analysis
Triage is fast and broad. Deep analysis is slow and precise. Volatility 3 earns its place here.
malfind
windows.malfind looks for memory regions that are executable,
writable, and not backed by a file. The structural fingerprint of:
- Reflective DLL injection.
- Shellcode injection (
VirtualAllocEx+WriteProcessMemory+CreateRemoteThread). - Process hollowing (when combined with mismatched image base).
A clean malfind does not mean nothing is there; a non-empty
malfind is almost always worth investigating.
Kernel inspection
windows.modscan enumerates kernel modules from the pool. Compare
against windows.modules (the live list) to find unlinked drivers —
the kernel equivalent of a DKOM-hidden process. windows.callbacks
and windows.ssdt reveal kernel hooks that user-mode telemetry
cannot see.
YARA scans
windows.yarascan.YaraScan runs rules across process address spaces.
Pair with curated rules (yara-rules/rules on GitHub) plus any internal
detections. Fastest way to confirm a known-bad payload.
Timeline
timeliner.Timeliner builds an event timeline from every plugin that
emits timestamps. Pipe to a CSV, load into Timesketch or a spreadsheet,
and follow the activity around the suspect timeframe. Cross-reference
against the on-disk timeline from the
MFT, the
USN journal, and
EVTX for the strongest narrative.
Stage 4: Carve
Some evidence is not in structured objects — it is just bytes.
bulk_extractor pulls:
- E-mail addresses (phishing pivot point).
- URLs and domain names (infrastructure pivot).
- IP addresses (network pivot).
- Credit cards, Bitcoin addresses, key material.
- ZIP and JPEG headers (carving for embedded artefacts).
Cross-reference what bulk_extractor finds with what triage and
pivoting showed. A C2 domain that appears in netscan and in raw
strings is stronger than either alone.
Stage 5: Conclude and document
A memory analysis is only as good as its report. Tie every claim to specific evidence:
- "PID 4128 (
svchost.exe) was injected with shellcode" → cite themalfindrow, the suspicious memory region, the parent PID. - "Outbound C2 to
203.0.113.5:443" → cite thenetscanrow, the associated process, and any matchingbulk_extractorstring hit. - "Credentials harvested via
lsass.exeaccess" → cite the handle (handlesplugin), the suspect PID, and any kernel callbacks that fired.
A finding without evidence is a guess. A guess in an IR report can cost the case.
What "done" looks like
- Every triage suspect has been resolved (false positive, here's why) or confirmed (here's the evidence).
- Deep-analysis plugins ran end-to-end, not just against suspects — you do not want to find out later that there was a second compromise you never looked at.
- The carving pass turned up nothing new, or what it turned up was reconciled with the structural findings.
- The timeline matches the suspected attack narrative — or, if it does not, the narrative gets updated.
Where ramparser fits
ramparser is the triage engine. It exists to make stage 1 disappear into the workflow — no environment, no symbol packs, no upload, just the answer. When triage points at something, you move to Volatility 3 for the rest.