Malware Detection
Memory forensics excels at detecting malware techniques that leave no artifacts on disk β injected code, process hollowing, rootkit hooks, and fileless payloads. These techniques should be run on any process of interest identified during process analysis.
Code Injection Detectionβ
malfind β Injected Code and PE Filesβ
Scans process VAD regions for memory-resident code that is suspicious based on three criteria: executable and writable protection (PAGE_EXECUTE_READWRITE), not backed by a file on disk, and containing PE headers or shellcode patterns. This is the primary plugin for detecting process injection and fileless malware.
# Scan all processes
vol.py -f <image> --profile=<profile> malfind
# Specific PID
vol.py -f <image> --profile=<profile> malfind -p <PID>
# Dump suspicious regions to files for further analysis
vol.py -f <image> --profile=<profile> malfind -p <PID> -D <output_dir>
vol3 -f <image> windows.malfind
vol3 -f <image> windows.malfind --pid <PID>
vol3 -f <image> windows.malfind --dump
malfind OutputEach hit shows the process, VAD start address, protection flags, and a hex/ASCII dump of the region. Look for:
MZheader at offset 0 β a PE file injected into process memory- Shellcode patterns (e.g.,
\x90\x90NOP sleds,\xfc\xe8common shellcode preambles) - False positives: JIT-compiled code from .NET/Java processes, packed executables β cross-reference with process reputation
Dump suspicious regions and submit to static analysis:
vol.py -f <image> --profile=<profile> malfind -D /cases/malfind_output/
# Run strings on each dump
strings -n 8 /cases/malfind_output/*.dmp | grep -iE "(http|cmd|powershell|registry|\\\\pipe)"
ldrmodules β Unlinked DLL Detectionβ
Compares three different in-memory lists of loaded modules (PEB InLoadOrderModuleList, PEB InMemoryOrderModuleList, and PEB InInitializationOrderModuleList) and the VAD tree. DLLs that appear in the VAD but are absent from the PEB lists are likely injected and hidden.
vol.py -f <image> --profile=<profile> ldrmodules -p <PID>
# Show only entries with discrepancies
vol.py -f <image> --profile=<profile> ldrmodules -p <PID> -v
No direct equivalent in Vol3. Use windows.dlllist combined with windows.vadinfo and manually compare mapped regions against the DLL list.
Each module is shown with three boolean columns: InLoad, InInit, InMem. A legitimately loaded DLL should be True in all three. A DLL showing False in any column β especially one with no mapped path β has been unlinked from the PEB, which is a common DLL injection concealment technique.
Process Hollowing Detectionβ
Process hollowing (a.k.a. RunPE) creates a legitimate process in suspended state, unmaps its memory, and replaces it with malicious code. Detection relies on cross-referencing multiple data sources:
Step 1 β Identify candidate processes:
# Look for processes with no PEB-listed executable path, or legitimate names with unusual paths
vol.py -f <image> --profile=<profile> ldrmodules | grep -v "True True True"
Step 2 β Check if the process executable on disk matches what is in memory:
# Dump the in-memory PE (procdump reconstructs from memory)
vol.py -f <image> --profile=<profile> procdump -p <PID> -D /cases/output/
# Hash and compare against known-good on-disk hash
sha256sum /cases/output/executable.<PID>.exe
Step 3 β Check VAD for anonymous executable regions (no mapped file):
vol.py -f <image> --profile=<profile> vadinfo -p <PID> | grep -A5 "EXECUTE"
A hollowed process typically has an anonymous EXECUTE_READWRITE VAD region at the base address where the original executable was mapped.
vol3 -f <image> windows.vadinfo --pid <PID>
vol3 -f <image> windows.procdump --pid <PID>
Service and Driver Analysisβ
svcscan β Windows Servicesβ
Scans memory for SERVICE_RECORD structures, listing all registered Windows services including those hidden by rootkits. Useful for finding malicious services created for persistence.
vol.py -f <image> --profile=<profile> svcscan
vol3 -f <image> windows.svcscan
- Services with binary paths pointing to
%TEMP%,%APPDATA%, or other non-standard locations - Services with generic or meaningless names
- Services with no description
- Services in
RUNNINGstate associated with suspicious processes
modules β Loaded Kernel Modulesβ
Lists loaded kernel modules (drivers) by walking the PsLoadedModuleList. Like pslist for processes, this list can be manipulated by rootkits.
vol.py -f <image> --profile=<profile> modules
vol3 -f <image> windows.modules
modscan β Kernel Module Pool Scanβ
Scans raw memory for LDR_DATA_TABLE_ENTRY pool tags to find kernel modules, including those hidden from PsLoadedModuleList.
vol.py -f <image> --profile=<profile> modscan
vol3 -f <image> windows.modscan
modules vs modscanAs with pslist/psscan for processes, modules present in modscan but not modules have been unlinked β a kernel-level rootkit indicator.
driverirp β Driver IRP Hook Detectionβ
Examines the IRP (I/O Request Packet) dispatch table for each loaded driver and flags any entries pointing outside the driver's normal address range. Hooked IRP handlers redirect I/O operations through attacker-controlled code β a common rootkit technique for intercepting file, network, or keyboard I/O.
vol.py -f <image> --profile=<profile> driverirp -r <driver_name_regex>
# Example β check all drivers
vol.py -f <image> --profile=<profile> driverirp
vol3 -f <image> windows.driverirp
ssdt β SSDT Hook Detection (Vol2 Only)β
Checks the System Service Descriptor Table (SSDT) for hooked entries. Rootkits hook the SSDT to intercept system calls and hide processes, files, or network connections. Entries pointing outside ntoskrnl.exe or win32k.sys address ranges are suspect.
vol.py -f <image> --profile=<profile> ssdt | grep -v "ntoskrnl\|win32k"
ssdt is a Vol2-only plugin. Vol3 does not have a direct equivalent β use windows.modules + windows.driverirp to identify suspicious kernel code.
apihooks β Userland API Hook Detection (Vol2 Only)β
Scans process memory for inline hooks and import address table (IAT) hooks in loaded modules. Hooks redirect API calls through attacker code before passing (or not passing) to the legitimate function.
vol.py -f <image> --profile=<profile> apihooks -p <PID>
apihooks is a Vol2-only plugin with no direct Vol3 equivalent.
Common inline hook indicators: a JMP or CALL instruction at the very start of a function redirecting to an address outside the module's normal range. The apihooks output flags these automatically.
YARA Scanningβ
Scan process memory or the full image with YARA rules β useful for detecting known malware families, shellcode patterns, or custom indicators.
# Vol2 β scan all process memory with a YARA rule file
vol.py -f <image> --profile=<profile> yarascan -y /rules/malware.yar
# Vol2 β scan specific PID
vol.py -f <image> --profile=<profile> yarascan -p <PID> -y /rules/malware.yar
# Vol2 β scan with inline YARA string
vol.py -f <image> --profile=<profile> yarascan -U "MZ\x90\x00"
# Scan process VAD regions
vol3 -f <image> windows.vadyarascan --yara-file /rules/malware.yar
# Scan physical memory layers
vol3 -f <image> yarascan.YaraScan --yara-file /rules/malware.yar
# Find Mimikatz artifacts
vol.py -f <image> --profile=<profile> yarascan -U "sekurlsa"
# Find PowerShell encoded command artifacts
vol.py -f <image> --profile=<profile> yarascan -U "FromBase64String"
# Find common shellcode preamble
vol.py -f <image> --profile=<profile> yarascan -U "\xfc\xe8\x82\x00\x00\x00"
# Metasploit Meterpreter
vol.py -f <image> --profile=<profile> yarascan -U "metsrv"