Understanding code injection requires understanding what legitimate process memory looks like — injection is the deviation from that baseline. Every technique leaves a different memory signature.
Injection Technique Memory Signatures
Technique | VAD Protection | File-backed? | In PEB lists? | MZ header?
───────────────────────────────────────────────────────────────────────────────────────
Legitimate DLL load | PAGE_EXECUTE_READ | Yes (.dll) | Yes (3/3) | Yes
Process hollowing | PAGE_EXECUTE_RW | No (private) | N/A (EXE) | Yes
Reflective DLL inj. | PAGE_EXECUTE_RW | No (private) | No (0/3) | Yes
Shellcode injection | PAGE_EXECUTE_RW | No (private) | N/A | Sometimes
PE injection | PAGE_EXECUTE_RW | No (private) | No (0/3) | Yes
windows.malfind — Injection Triage
# Run malfind against all processes
vol.py -f memory.raw windows.malfind
# Output fields:
# Process Name | PID | Start | End | Tag | Protection | Hexdump | Disassembly
# Run against a specific PID
vol.py -f memory.raw windows.malfind --pid 4492
# Example malfind output (injection):
# PID: 4492 Name: svchost.exe
# Start: 0x1f0000 End: 0x23ffff
# VadS Protection: PAGE_EXECUTE_READWRITE
# 4d 5a 90 00 03 00 00 00 MZ......
# The 0x4d5a (MZ) header confirms a PE image in private RWX memory
# Example malfind output (JIT false positive):
# PID: 8234 Name: chrome.exe
# Start: 0x7f0000 End: 0x8effff
# VadS Protection: PAGE_EXECUTE_READ
# 55 8b ec 83 ec 20 ... (x86 function prologue — no MZ header)
# → No MZ header = JIT code, not a PE image = likely false positive
# Dump the suspicious region for static analysis
vol.py -f memory.raw windows.malfind --pid 4492 --dump
# Output: pid.4492.vad.0x1f0000-0x23ffff.dmp
# Analyze with: file pid.4492.*.dmp; strings pid.4492.*.dmp; xxd pid.4492.*.dmp | head
windows.ldrmodules — Reflective Injection Detection
# Check module lists for a specific PID
vol.py -f memory.raw windows.ldrmodules --pid 4492
# Output columns:
# PID | Process | Base | InLoad | InMem | InInit | MappedPath
# Legitimate DLL (all True):
# 4492 svchost.exe 0x7ff6f0000000 True True True \Windows\System32\svchost.exe
# Reflectively injected DLL (all False):
# 4492 svchost.exe 0x1f0000000000 False False False (no path)
# Partially present (anomalous — may indicate manual PEB unlinking):
# 4492 svchost.exe 0x2a0000000000 True True False \Windows\System32\ntdll.dll
# False/False/False with no MappedPath = reflective injection
# The DLL is in memory but the Windows loader has no knowledge of it
Process Hollowing Detection
# Step 1: Check if the process's in-memory executable base matches the on-disk binary
# windows.cmdline reveals if svchost is missing expected -k argument
vol.py -f memory.raw windows.cmdline --pid 4492
# Hollowed svchost: "C:\Windows\System32\svchost.exe" (no -k flag) = anomalous
# Legitimate svchost: "C:\Windows\System32\svchost.exe -k netsvcs -p"
# Step 2: Check the VAD for the main executable region
vol.py -f memory.raw windows.vadinfo --pid 4492 | head -30
# Legitimate: \Windows\System32\svchost.exe appears as a file-mapped region
# Hollowed: executable region shows as private (VadS) not file-mapped
# Step 3: Dump the in-memory executable for hash comparison
vol.py -f memory.raw windows.dumpfiles --pid 4492 --name svchost.exe
# OR use procdump:
vol.py -f memory.raw windows.dumpfiles -o 0x[EPROCESS_offset]
# Step 4: Hash the dumped executable
sha256sum pid.4492.0x*.dmp
# Step 5: Compare against known-good svchost hash
# Get reference hash from clean Windows system:
# sha256sum C:\Windows\System32\svchost.exe (on a clean system)
# Or use VirusTotal to look up the hash
Full Injection Investigation Workflow
#!/bin/bash
# Systematic injection investigation for a suspicious PID
PID=4492
MEMORY_IMAGE="memory.raw"
OUTPUT_DIR="./injection_analysis"
mkdir -p "$OUTPUT_DIR"
echo "[1] Process context"
vol.py -f "$MEMORY_IMAGE" windows.pslist --pid "$PID" > "$OUTPUT_DIR/01_pslist.txt"
vol.py -f "$MEMORY_IMAGE" windows.cmdline --pid "$PID" > "$OUTPUT_DIR/02_cmdline.txt"
vol.py -f "$MEMORY_IMAGE" windows.dlllist --pid "$PID" > "$OUTPUT_DIR/03_dlllist.txt"
echo "[2] Network connections"
vol.py -f "$MEMORY_IMAGE" windows.netscan | grep "$PID" > "$OUTPUT_DIR/04_netscan.txt"
echo "[3] Injection detection"
vol.py -f "$MEMORY_IMAGE" windows.malfind --pid "$PID" > "$OUTPUT_DIR/05_malfind.txt"
vol.py -f "$MEMORY_IMAGE" windows.ldrmodules --pid "$PID" > "$OUTPUT_DIR/06_ldrmodules.txt"
vol.py -f "$MEMORY_IMAGE" windows.vadinfo --pid "$PID" > "$OUTPUT_DIR/07_vadinfo.txt"
echo "[4] Dump suspicious regions for static analysis"
vol.py -f "$MEMORY_IMAGE" windows.malfind --pid "$PID" --dump \
--output-dir "$OUTPUT_DIR/dumped/"
echo "[5] Privileges check"
vol.py -f "$MEMORY_IMAGE" windows.privileges --pid "$PID" > "$OUTPUT_DIR/08_privileges.txt"
echo "Investigation artifacts in $OUTPUT_DIR"