GNU/Linux Memory Forensics: Is the Compromise Still Live?
Following the evidence in memory to determine what survived after an attack

It's easy to think of memory forensics purely as a hunt for something malicious. On this case, a GNU/Linux server that had already been through a full attack chain, initial access, privilege escalation, and persistence via a hidden root-equivalent user account, with some tracks cleared from disk on the way out, the investigation ended somewhere different. No live implant found in memory. One confidently ruled out.
That distinction matters. The open question by the time memory analysis started wasn't "did an attack happen." That was already established through other evidence. It was "is there still an active RAT resident in memory, right now." That's really what this whole discipline is for: proving what happened and establishing what is still happening are two different forensic questions, and only one of them can be answered from disk. Memory analysis exists to answer the second one, with evidence, at the exact moment a snapshot was taken.
A note on tooling. This case was analysed on Volatility 2.6 with the underscore-style plugin names (linux_pstree, linux_malfind), the version most of us cut our teeth on. Volatility 3 is the current standard now, with renamed, auto-detecting plugins. AVML, by contrast, has aged well and remains the right acquisition tool today, with one behaviour change worth flagging below. A full comparison table is at the end.
Acquisition: AVML
Windows acquisition tools generally assume a fixed set of APIs that don't vary much between builds. GNU/Linux doesn't offer that luxury. Kernel versions, available memory devices, and compiled-in support for reading physical memory differ from distribution to distribution and even between kernel builds on the same distribution. That variability is exactly why AVML (Acquire Volatile Memory for Linux), built by Microsoft, is the right default. It's a single static binary with no external dependencies, which matters enormously under incident response time pressure, when you often don't know the exact kernel version of the box in front of you and can't afford a tool that needs compiling against it.
AVML writes directly to /dev/mem or /proc/kcore, depending on what the running kernel exposes, and produces a raw image in the same format Volatility expects.
Tooling note: AVML is still actively maintained by Microsoft and remains a solid default today. Two things have changed since this case. Newer builds default to the LiME output format rather than raw (Volatility 3 reads both natively), and on kernels with kernel_lockdown enabled, AVML cannot acquire memory at all. Worth checking for on any recent kernel before you rely on it in the field.
Working the Dump: The Volatility Workflow
Once the raw image exists, the Volatility Framework does the analytical work, walking the kernel's own data structures inside the memory dump the same way the live OS would, except offline and after the fact, via a GNU/Linux-specific profile. What follows is the order I ran plugins in on this case.
1. linux_pstree: Map the Process Tree
The first step after establishing the correct profile is mapping the process tree. linux_pstree returned a clean hierarchy: systemd as PID 1, normal desktop session processes (gnome-session, gnome-shell, pulseaudio, dbus-daemon, ssh-agent) with sensible parentage, and nothing masquerading under a process it had no business being a child of.
This matters as much as an anomaly would have. The attacker's persistence mechanism on this host was a hidden user account rather than an in-memory process hierarchy trick, so a clean pstree here isn't a dead end. It's confirmation that whatever else happened on this box, the attacker wasn't relying on live process injection to maintain a foothold at the moment of capture.
2. linux_malfind: Check for Injected Code
linux_malfind scans process memory for regions marked executable with no backing file on disk, the signature left behind by code injection and in-memory-only implants. On this host, it returned nothing.
A no-hit result from malfind is a real finding, not a null one, but it isn't proof on its own. A clean malfind result rules out one specific signature: an executable memory region with no backing file on disk. It doesn't rule out a RAT that never touched memory in a way malfind catches, or one that had already been stopped by the time acquisition happened. What the result actually supports, on its own, is narrower than "no RAT." It's "no memory region matching the pattern malfind looks for." The broader conclusion, that no active implant was resident in memory at capture time, comes later, once this result is read alongside the process tree and the network state rather than on its own.
3. linux_netstat: Network State From Memory
linux_netstat recovers connection state directly from kernel structures in the memory image, rather than trusting a live netstat binary the attacker could plausibly have tampered with. This is one of memory forensics' clearest advantages over disk analysis, since a closed connection from before acquisition simply isn't recoverable from disk at all. The output here returned two active UDP sessions and no active TCP sessions.
Both sessions resolved to explainable, benign traffic: one a local connection, the other addressed to the network's default gateway. Neither pattern matched what a reverse shell or an active C2 beacon would look like: no unexplained outbound TCP connection to an external host, no traffic on an unusual port, nothing addressed outside the local network. That's not the same as proving no C2 channel existed. A dormant beacon, an implant using a covert channel netstat wouldn't surface as ordinary socket state, or malware that was present but not actively communicating at the exact second of capture would all look identical to this result. What the memory evidence actually supports is narrower and more honest: no indication of an active implant or active attacker communication at the time of acquisition. Combined with the clean process tree and the absence of injected code, that's a reasonably strong basis for a conclusion, but it's a conclusion built from correlation across three independent results, not from any one of them ruling anything out by itself.
Why the Negative Result Still Mattered
It would be a mistake to read "no malware found in memory" as "memory analysis added nothing" on this case. The disk-based investigation had already established the attack chain: initial access, privilege escalation, a hidden persistence account, and evidence the attacker had cleared some artefacts from /tmp on their way out. Disk forensics can tell you what happened. It can't tell you, on its own, whether the compromise is still live right now, with an implant sitting in RAM and potentially still communicating outbound. That's the specific question memory analysis exists to answer, and here the answer, built from the process tree, the injected-code check, and the network state read together rather than any single result in isolation, was no.
Confirming that changed the shape of the response. An active RAT in memory means immediate isolation and a live-response posture. A memory result with no indication of an active implant, on top of an already-understood attack chain, means the response can move to remediation and hardening of the persistence mechanism that was found, without an open question about ongoing outbound communication hanging over the rest of the investigation.
What This Case Illustrates
A few things stood out from running this discipline against a GNU/Linux target specifically.
Acquisition tooling has to match the OS's constraints, not just its architecture. GNU/Linux kernel versions, available memory devices, and compiled-in support for reading physical memory vary widely across distributions and builds, which is exactly why AVML's dependency-free, single-static-binary design matters as much as it does.
No single plugin proves a system clean. This case built its conclusion from a chain of results, a clean process tree, an empty
malfindresult, and network sessions that resolved to nothing suspicious, read together and cross-checked against each other. Any one of them in isolation would support a narrower, more hedged claim than the conclusion the combination supports.Proving what happened and establishing what is still happening are different forensic questions. The attack chain here was already established through other evidence. What memory analysis added was the second answer: confirmation of the compromise's state at the exact moment of capture, which is what actually determines whether a response plan calls for immediate isolation or can move straight to remediation.
Command Comparison: Volatility 2 (Then) vs Volatility 3 (Now)
| What you're checking | Volatility 2.6 (used in this case) | Volatility 3 (current) |
|---|---|---|
| Process tree | linux_pstree |
linux.pstree |
| Injected code detection | linux_malfind |
linux.malfind |
| Network connections | linux_netstat |
linux.sockstat |
The naming convention changed the most visibly. Volatility 2's GNU/Linux plugins used an underscore prefix (linux_pstree), while Volatility 3 uses a dotted namespace (linux.pstree), consistent across every platform it supports. linux_netstat's closest current equivalent is linux.sockstat, which covers the same ground, active sockets per process, with more socket-family detail than the old plugin exposed. None of the underlying reasoning changes. You're still looking for the same anomaly, or the same reassuring absence of one.
Key Takeaways for Practitioners
Pick acquisition tooling for the constraints of the target OS, not just habit. AVML's dependency-free design exists because GNU/Linux kernel variability makes anything else unreliable under time pressure.
Learn the question each plugin answers, not just its name: process lineage, hidden processes, live connections, injected code. The naming changes between tool versions; what you're actually checking for doesn't.
Don't treat a clean
malfind/linux_malfindresult as proof on its own, and don't treat it as "nothing to report" either. It rules out one specific signature. The broader conclusion comes from reading it alongside everything else.State conclusions at the level the evidence actually supports. "No indication of an active implant at the time of acquisition" is more defensible, and just as useful to a response plan, than "ruled out."
Memory analysis's job isn't only to find malware. It's to answer, with correlated evidence, whether a compromise is still active right now, as distinct from whether it happened at all. That answer shapes everything about how the response proceeds from there.
This article is drawn from a digital forensics investigation into a GNU/Linux host that had already been through a documented attack chain, initial access, privilege escalation, and persistence via a hidden user account, using AVML for acquisition and the Volatility Framework for analysis.





