mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-10 21:24:56 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
234 lines
9.0 KiB
Python
234 lines
9.0 KiB
Python
#!/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]]")
|