npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
NIST CSF 2.0
MITRE D3FEND
When to Use
- EDR alerts on suspicious API call sequences (VirtualAllocEx + WriteProcessMemory + CreateRemoteThread)
- A legitimate process (explorer.exe, svchost.exe) exhibits unexpected network connections or file operations
- Memory forensics reveals executable code in memory regions that should not contain it
- Investigating living-off-the-land attacks where malware hides inside trusted processes
- Building detection logic for specific injection techniques in EDR or SIEM rules
Do not use for standard DLL loading analysis; injection implies unauthorized code placement in a process without that process's cooperation.
Prerequisites
- Volatility 3 for memory forensics analysis of injection artifacts
- Sysmon configured with Event IDs 8 (CreateRemoteThread) and 10 (ProcessAccess)
- API Monitor or x64dbg for observing injection API calls in real-time
- Process Hacker or Process Explorer for inspecting process memory regions
- Understanding of Windows memory management (VirtualAlloc, VAD, page protections)
- Isolated analysis environment for safe malware execution and monitoring
Workflow
Step 1: Identify Injection via Memory Forensics
Use Volatility to detect injected code in process memory:
# malfind: Primary injection detection plugin
vol3 -f memory.dmp windows.malfind
# malfind detects:
# - Memory regions with PAGE_EXECUTE_READWRITE (RWX) protection
# - PE headers (MZ signature) in non-image VAD entries
# - Executable memory not backed by a file on disk
# Filter by specific process
vol3 -f memory.dmp windows.malfind --pid 852
# Dump injected memory regions for analysis
vol3 -f memory.dmp windows.malfind --dump
# Check VAD (Virtual Address Descriptor) tree for anomalies
vol3 -f memory.dmp windows.vadinfo --pid 852
# Detect hollowed processes (mapped image doesn't match disk)
vol3 -f memory.dmp windows.hollowfindStep 2: Classify the Injection Technique
Identify which injection method was used based on artifacts:
Process Injection Techniques and Detection Artifacts:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Classic DLL Injection
APIs: OpenProcess -> VirtualAllocEx -> WriteProcessMemory -> CreateRemoteThread
Artifact: Loaded DLL in target process not present in known-good baseline
Detection: New DLL in dlllist not matching disk hash, CreateRemoteThread event
2. Process Hollowing (RunPE)
APIs: CreateProcess(SUSPENDED) -> NtUnmapViewOfSection -> VirtualAllocEx ->
WriteProcessMemory -> SetThreadContext -> ResumeThread
Artifact: Process image in memory doesn't match file on disk
Detection: hollowfind plugin, mismatched PE headers vs disk file
3. APC Injection
APIs: OpenProcess -> VirtualAllocEx -> WriteProcessMemory -> QueueUserAPC
Artifact: Alertable thread has queued APC pointing to injected code
Detection: Thread start addresses outside known modules
4. Thread Hijacking
APIs: OpenProcess -> VirtualAllocEx -> WriteProcessMemory ->
SuspendThread -> GetThreadContext -> SetThreadContext -> ResumeThread
Artifact: Thread instruction pointer changed to injected code
Detection: Thread context modification, EIP/RIP outside module boundaries
5. Reflective DLL Injection
APIs: VirtualAllocEx -> WriteProcessMemory -> CreateRemoteThread (to reflective loader)
Artifact: DLL loaded in memory but NOT in loaded module list
Detection: malfind (PE in non-image memory), module not in ldrmodules
6. Process Doppelganging
APIs: NtCreateTransaction -> NtCreateFile(transacted) -> NtWriteFile ->
NtCreateSection -> NtRollbackTransaction -> NtCreateProcessEx
Artifact: Process created from transacted file that was rolled back
Detection: Process with no corresponding file on disk
7. AtomBombing
APIs: GlobalAddAtom -> NtQueueApcThread (with GlobalGetAtomName)
Artifact: Code stored in global atom table, APC triggers copy to target
Detection: Unusual atom table entries, APC injection indicatorsStep 3: Detect Injection via Sysmon Events
Analyze Sysmon and Windows Event Log data:
# Sysmon Event ID 8: CreateRemoteThread
# Detect when one process creates a thread in another
wevtutil qe "Microsoft-Windows-Sysmon/Operational" \
/q:"*[System[EventID=8]]" /f:text /c:20
# Sysmon Event ID 10: ProcessAccess
# Detect suspicious access rights to other processes
# DesiredAccess containing PROCESS_VM_WRITE (0x0020) + PROCESS_CREATE_THREAD (0x0002)
wevtutil qe "Microsoft-Windows-Sysmon/Operational" \
/q:"*[System[EventID=10]]" /f:text /c:20
# Sysmon Event ID 1: Process Creation
# Detect process hollowing via suspicious parent-child relationships
wevtutil qe "Microsoft-Windows-Sysmon/Operational" \
/q:"*[System[EventID=1]]" /f:text /c:20# Parse Sysmon events for injection indicators
import xml.etree.ElementTree as ET
import subprocess
# Query CreateRemoteThread events
result = subprocess.run(
["wevtutil", "qe", "Microsoft-Windows-Sysmon/Operational",
"/q:*[System[EventID=8]]", "/f:xml", "/c:100"],
capture_output=True, text=True
)
suspicious_injections = []
for event_xml in result.stdout.split("</Event>"):
if not event_xml.strip():
continue
try:
root = ET.fromstring(event_xml + "</Event>")
ns = {"e": "http://schemas.microsoft.com/win/2004/08/events/event"}
data = {}
for d in root.findall(".//e:EventData/e:Data", ns):
data[d.get("Name")] = d.text
source = data.get("SourceImage", "")
target = data.get("TargetImage", "")
# Flag injections from unusual sources into system processes
system_procs = ["svchost.exe", "explorer.exe", "lsass.exe", "winlogon.exe"]
if any(p in target.lower() for p in system_procs):
if not any(p in source.lower() for p in ["csrss.exe", "services.exe", "lsass.exe"]):
print(f"[!] Suspicious injection: {source} -> {target}")
suspicious_injections.append(data)
except:
passStep 4: Analyze Injected Code
Examine the injected payload to understand its purpose:
# Dump injected code from Volatility malfind
vol3 -f memory.dmp windows.malfind --pid 852 --dump
# Analyze the dumped region
file malfind.*.dmp
# If it contains a PE (MZ header), analyze as a standalone executable
python3 << 'PYEOF'
import pefile
# Attempt to parse as PE
try:
pe = pefile.PE("malfind.852.0x400000.dmp")
print("Injected PE detected!")
print(f" Architecture: {'x64' if pe.FILE_HEADER.Machine == 0x8664 else 'x86'}")
print(f" Imports:")
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
print(f" {entry.dll.decode()}: {len(entry.imports)} functions")
except:
print("Not a valid PE - likely shellcode")
# Analyze as shellcode
with open("malfind.852.0x400000.dmp", "rb") as f:
shellcode = f.read()
print(f" Size: {len(shellcode)} bytes")
print(f" First bytes: {shellcode[:32].hex()}")
PYEOF
# Disassemble shellcode
python3 -c "
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
with open('malfind.852.0x400000.dmp', 'rb') as f:
code = f.read()[:256]
md = Cs(CS_ARCH_X86, CS_MODE_64)
for insn in md.disasm(code, 0x400000):
print(f' 0x{insn.address:X}: {insn.mnemonic} {insn.op_str}')
"
# Scan with YARA for known payloads
vol3 -f memory.dmp yarascan.YaraScan --pid 852 --yara-file malware_rules.yarStep 5: Map to MITRE ATT&CK
Classify detected techniques in the ATT&CK framework:
MITRE ATT&CK Process Injection Sub-Techniques (T1055):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
T1055.001 Dynamic-link Library Injection
T1055.002 Portable Executable Injection
T1055.003 Thread Execution Hijacking
T1055.004 Asynchronous Procedure Call (APC)
T1055.005 Thread Local Storage
T1055.008 Ptrace System Calls (Linux)
T1055.009 Proc Memory (/proc/pid/mem - Linux)
T1055.011 Extra Window Memory Injection
T1055.012 Process Hollowing
T1055.013 Process Doppelganging
T1055.014 VDSO Hijacking (Linux)
T1055.015 ListPlantingStep 6: Create Detection Signatures
Build detection rules for the identified technique:
# Sigma rule for CreateRemoteThread injection
title: Suspicious CreateRemoteThread into System Process
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 8
TargetImage|endswith:
- '\svchost.exe'
- '\explorer.exe'
- '\lsass.exe'
filter:
SourceImage|endswith:
- '\csrss.exe'
- '\services.exe'
- '\svchost.exe'
condition: selection and not filter
level: highKey Concepts
| Term | Definition |
|---|---|
| Process Injection | Technique of executing code within the address space of another process, typically to evade detection and inherit the target's trust level |
| Process Hollowing | Creating a legitimate process in suspended state, unmapping its memory, writing malicious code, and resuming execution to masquerade as the legitimate process |
| Reflective DLL Injection | Loading a DLL into a process's memory without using the Windows loader, so the DLL does not appear in the loaded module list |
| APC Injection | Queuing an Asynchronous Procedure Call to a thread in the target process, causing it to execute injected code when the thread enters an alertable state |
| VAD (Virtual Address Descriptor) | Windows kernel structure describing memory regions in a process; anomalous VAD entries (RWX permissions, non-image PE) indicate injection |
| CreateRemoteThread | Windows API creating a thread in another process; the primary mechanism for classic DLL injection and many other injection techniques |
| PAGE_EXECUTE_READWRITE | Memory protection allowing read, write, and execute; rarely used by legitimate applications, common indicator of injected code |
Tools & Systems
- Volatility (malfind): Memory forensics plugin detecting injected code through VAD analysis and PE header scanning in non-image memory regions
- Sysmon: System Monitor providing detailed Windows event logging including CreateRemoteThread (EID 8) and ProcessAccess (EID 10)
- Process Hacker: Advanced process management tool showing detailed memory regions, thread stacks, and injected modules
- API Monitor: Windows tool for monitoring and logging API calls made by processes, useful for observing injection sequences in real-time
- pe-sieve: Tool scanning running processes for signs of code injection, hooking, and hollowing
Common Scenarios
Scenario: Investigating a Hollowed svchost.exe Process
Context: EDR alerts on svchost.exe making HTTPS connections to an external IP. Svchost.exe should only communicate with Microsoft services. Memory analysis is needed to confirm process hollowing.
Approach:
- Capture memory dump of the suspicious svchost.exe process
- Run Volatility
malfindto detect injected PE in the process memory - Compare the in-memory image base with the on-disk svchost.exe file hash
- Check the process parent (should be services.exe) and creation parameters
- Dump the hollowed executable from memory and analyze with Ghidra
- Run
netscanto confirm the network connections from the hollowed process - Scan dumped code with YARA for malware family identification
Pitfalls:
- Assuming all svchost.exe instances are identical (each loads different service DLLs)
- Not checking the parent process (hollowed processes often have wrong parents)
- Relying only on process name matching (attackers specifically target svchost.exe because multiple instances are expected)
- Missing the injection source process that may have already terminated
Output Format
PROCESS INJECTION ANALYSIS REPORT
====================================
Dump File: memory.dmp
Analysis Tool: Volatility 3.2 + Sysmon
INJECTION DETECTED
Target Process: svchost.exe (PID: 852)
Source Process: malware.exe (PID: 2184) [terminated]
Technique: Process Hollowing (T1055.012)
EVIDENCE
malfind Results:
PID 852 (svchost.exe):
Address: 0x00400000
Size: 184,320 bytes
Protection: PAGE_EXECUTE_READWRITE
Header: MZ (PE32 executable)
NOT backed by disk file
Process Verification:
Expected Image: C:\Windows\System32\svchost.exe (SHA-256: aaa...)
In-Memory Image: Unknown PE (SHA-256: bbb...)
Result: MISMATCH - HOLLOWED PROCESS
Sysmon Events:
[4688] malware.exe (PID 2184) created svchost.exe (PID 852) SUSPENDED
[10] malware.exe accessed svchost.exe with PROCESS_VM_WRITE
[8] malware.exe created remote thread in svchost.exe
INJECTED PAYLOAD ANALYSIS
SHA-256: bbb123def456...
YARA Match: CobaltStrike_Beacon_x64
Type: Cobalt Strike Beacon (HTTP)
C2: hxxps://185.220.101[.]42/updates
MITRE ATT&CK
T1055.012 Process Hollowing
T1071.001 Web Protocols (HTTPS C2)
T1036.005 Match Legitimate Name (svchost.exe)References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.6 KB
Process Injection Detection API Reference
Volatility 3 Plugins
# Detect injected code (RWX memory, PE headers in non-image VADs)
vol3 -f memory.dmp windows.malfind
vol3 -f memory.dmp windows.malfind --pid 1234
# List processes
vol3 -f memory.dmp windows.pslist
# Scan for hidden processes
vol3 -f memory.dmp windows.psscan
# List DLLs for a process
vol3 -f memory.dmp windows.dlllist --pid 1234
# Dump injected code
vol3 -f memory.dmp windows.malfind --dump --pid 1234
# List threads
vol3 -f memory.dmp windows.threads --pid 1234
# VAD tree (memory regions)
vol3 -f memory.dmp windows.vadinfo --pid 1234Injection Techniques and API Sequences
| Technique | API Sequence |
|---|---|
| Classic DLL | OpenProcess -> VirtualAllocEx -> WriteProcessMemory -> CreateRemoteThread |
| Process Hollowing | CreateProcess(SUSPENDED) -> NtUnmapViewOfSection -> WriteProcessMemory -> ResumeThread |
| APC Injection | OpenThread -> VirtualAllocEx -> WriteProcessMemory -> QueueUserAPC |
| Reflective DLL | VirtualAlloc -> memcpy -> CreateThread (in-process) |
| Thread Hijacking | OpenThread -> SuspendThread -> SetThreadContext -> ResumeThread |
Sysmon Event IDs for Injection
| Event ID | Name | Relevance |
|---|---|---|
| 1 | ProcessCreate | Hollowed process creation (SUSPENDED) |
| 7 | ImageLoaded | Reflective DLL loads (unsigned) |
| 8 | CreateRemoteThread | Classic injection indicator |
| 10 | ProcessAccess | PROCESS_VM_WRITE + PROCESS_CREATE_THREAD |
| 25 | ProcessTampering | Image file replaced (hollowing) |
Sysmon Config for Injection Detection
<Sysmon schemaversion="4.90">
<EventFiltering>
<ProcessAccess onmatch="include">
<GrantedAccess condition="is">0x1F0FFF</GrantedAccess>
<GrantedAccess condition="is">0x1FFFFF</GrantedAccess>
</ProcessAccess>
<CreateRemoteThread onmatch="exclude">
<SourceImage condition="is">C:\Windows\System32\csrss.exe</SourceImage>
</CreateRemoteThread>
</EventFiltering>
</Sysmon>python-evtx Usage
import Evtx.Evtx as evtx
with evtx.Evtx("Sysmon.evtx") as log:
for record in log.records():
xml = record.xml()
if "<EventID>8</EventID>" in xml:
print("CreateRemoteThread:", record.timestamp())Suspicious Parent-Child Relationships
| Parent | Child | Indicator |
|---|---|---|
| winword.exe | cmd.exe, powershell.exe | Macro execution |
| svchost.exe | cmd.exe, powershell.exe | Service-based injection |
| explorer.exe | mshta.exe | COM hijack / LNK abuse |
| outlook.exe | powershell.exe | Email macro execution |
Scripts 1
agent.py9.0 KB
#!/usr/bin/env python3
"""Process injection detection agent using Volatility and Sysmon analysis."""
import json
import os
import subprocess
import sys
from datetime import datetime
try:
import Evtx.Evtx as evtx
HAS_EVTX = True
except ImportError:
HAS_EVTX = False
INJECTION_TECHNIQUES = {
"classic_dll_injection": {
"apis": ["OpenProcess", "VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread"],
"sysmon_events": [8, 10],
"description": "Classic DLL injection via remote thread creation",
},
"process_hollowing": {
"apis": ["CreateProcess(SUSPENDED)", "NtUnmapViewOfSection", "VirtualAllocEx",
"WriteProcessMemory", "SetThreadContext", "ResumeThread"],
"sysmon_events": [1, 10],
"description": "Process hollowing - replace legitimate process image",
},
"apc_injection": {
"apis": ["OpenThread", "VirtualAllocEx", "WriteProcessMemory", "QueueUserAPC"],
"sysmon_events": [8, 10],
"description": "APC queue injection via QueueUserAPC",
},
"reflective_dll": {
"apis": ["VirtualAlloc", "memcpy", "CreateThread"],
"sysmon_events": [7],
"description": "Reflective DLL loading without LoadLibrary",
},
"process_doppelganging": {
"apis": ["CreateTransaction", "CreateFileTransacted", "NtCreateSection",
"NtCreateProcessEx", "RollbackTransaction"],
"sysmon_events": [1],
"description": "Process doppelganging via NTFS transactions",
},
}
def run_volatility_malfind(memory_dump, pid=None):
"""Run Volatility malfind plugin to detect injected code."""
if not os.path.exists(memory_dump):
return {"error": f"Memory dump not found: {memory_dump}"}
cmd = ["vol3", "-f", memory_dump, "windows.malfind"]
if pid:
cmd.extend(["--pid", str(pid)])
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
findings = []
current = {}
for line in result.stdout.splitlines():
if line.strip() and not line.startswith("Volatility"):
parts = line.split()
if len(parts) >= 6 and parts[0].isdigit():
if current:
findings.append(current)
current = {
"pid": parts[0],
"process": parts[1] if len(parts) > 1 else "",
"address": parts[2] if len(parts) > 2 else "",
"protection": parts[4] if len(parts) > 4 else "",
}
if current:
findings.append(current)
return {"findings": findings, "count": len(findings)}
except FileNotFoundError:
return {"error": "Volatility 3 (vol3) not installed"}
except subprocess.TimeoutExpired:
return {"error": "Analysis timed out after 300s"}
def run_volatility_hollowfind(memory_dump):
"""Detect process hollowing via VAD/PEB image path mismatch."""
if not os.path.exists(memory_dump):
return {"error": f"Memory dump not found: {memory_dump}"}
cmd = ["vol3", "-f", memory_dump, "windows.pslist"]
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
processes = []
for line in result.stdout.splitlines():
parts = line.split()
if len(parts) >= 4 and parts[0].isdigit():
processes.append({
"pid": parts[0],
"ppid": parts[1] if len(parts) > 1 else "",
"name": parts[2] if len(parts) > 2 else "",
"threads": parts[3] if len(parts) > 3 else "",
})
return {"processes": processes, "count": len(processes)}
except FileNotFoundError:
return {"error": "Volatility 3 not installed"}
except subprocess.TimeoutExpired:
return {"error": "Analysis timed out"}
def scan_sysmon_injection_events(evtx_path):
"""Scan Sysmon logs for injection-related events."""
if not HAS_EVTX:
return {"error": "python-evtx not installed (pip install python-evtx)"}
if not os.path.exists(evtx_path):
return {"error": f"EVTX file not found: {evtx_path}"}
injection_events = []
with evtx.Evtx(evtx_path) as log:
for record in log.records():
try:
xml = record.xml()
if "<EventID>8</EventID>" in xml:
injection_events.append({
"event_id": 8,
"type": "CreateRemoteThread",
"timestamp": record.timestamp().isoformat(),
"snippet": xml[:500],
})
elif "<EventID>10</EventID>" in xml:
if "PROCESS_VM_WRITE" in xml or "PROCESS_CREATE_THREAD" in xml:
injection_events.append({
"event_id": 10,
"type": "ProcessAccess (injection prep)",
"timestamp": record.timestamp().isoformat(),
"snippet": xml[:500],
})
except Exception:
continue
return {"injection_events": len(injection_events), "events": injection_events[:50]}
def detect_rwx_memory_regions():
"""Detect processes with suspicious RWX memory regions (Windows)."""
ps_cmd = (
"Get-Process | ForEach-Object { "
"$p = $_; "
"try { "
"$modules = $p.Modules | Select-Object -First 1; "
"[PSCustomObject]@{Name=$p.ProcessName; PID=$p.Id; WorkingSet=$p.WorkingSet64} "
"} catch {} } | ConvertTo-Json"
)
try:
result = subprocess.run(
["powershell", "-Command", ps_cmd],
capture_output=True, text=True, timeout=15
)
if result.returncode == 0 and result.stdout.strip():
return json.loads(result.stdout)
return {"error": result.stderr.strip()}
except Exception as e:
return {"error": str(e)}
def check_unusual_parent_child():
"""Detect unusual parent-child process relationships."""
suspicious_combos = [
("svchost.exe", "cmd.exe"),
("svchost.exe", "powershell.exe"),
("explorer.exe", "cmd.exe"),
("winword.exe", "powershell.exe"),
("winword.exe", "cmd.exe"),
("excel.exe", "powershell.exe"),
("outlook.exe", "powershell.exe"),
]
ps_cmd = (
"Get-WmiObject Win32_Process | Select-Object ProcessId, Name, ParentProcessId | "
"ConvertTo-Json"
)
try:
result = subprocess.run(
["powershell", "-Command", ps_cmd],
capture_output=True, text=True, timeout=15
)
if result.returncode != 0:
return {"error": result.stderr.strip()}
processes = json.loads(result.stdout)
if not isinstance(processes, list):
processes = [processes]
pid_map = {p["ProcessId"]: p["Name"] for p in processes}
suspicious = []
for proc in processes:
parent_name = pid_map.get(proc.get("ParentProcessId"), "").lower()
child_name = (proc.get("Name") or "").lower()
for p, c in suspicious_combos:
if parent_name == p.lower() and child_name == c.lower():
suspicious.append({
"parent": parent_name,
"child": child_name,
"child_pid": proc["ProcessId"],
"risk": "HIGH",
})
return {"suspicious_relationships": suspicious, "count": len(suspicious)}
except Exception as e:
return {"error": str(e)}
def generate_report(memory_dump=None, sysmon_evtx=None):
"""Generate process injection detection report."""
report = {
"timestamp": datetime.utcnow().isoformat() + "Z",
"techniques_catalog": {k: v["description"] for k, v in INJECTION_TECHNIQUES.items()},
}
if memory_dump:
report["malfind"] = run_volatility_malfind(memory_dump)
if sysmon_evtx:
report["sysmon_injection"] = scan_sysmon_injection_events(sysmon_evtx)
report["parent_child_anomalies"] = check_unusual_parent_child()
return report
if __name__ == "__main__":
action = sys.argv[1] if len(sys.argv) > 1 else "help"
if action == "malfind" and len(sys.argv) > 2:
pid = int(sys.argv[3]) if len(sys.argv) > 3 else None
print(json.dumps(run_volatility_malfind(sys.argv[2], pid), indent=2, default=str))
elif action == "sysmon" and len(sys.argv) > 2:
print(json.dumps(scan_sysmon_injection_events(sys.argv[2]), indent=2, default=str))
elif action == "parent-child":
print(json.dumps(check_unusual_parent_child(), indent=2))
elif action == "report":
mem = sys.argv[2] if len(sys.argv) > 2 else None
sysmon = sys.argv[3] if len(sys.argv) > 3 else None
print(json.dumps(generate_report(mem, sysmon), indent=2, default=str))
else:
print("Usage: agent.py [malfind <memory.dmp> [pid]|sysmon <Sysmon.evtx>|parent-child|report [mem] [sysmon]]")