Files
mukul975 27c6414ca5 Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills:
- scripts/agent.py: 80-150 line Python agents using real libraries (impacket,
  boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.)
- references/api-reference.md: real API documentation with method signatures
- LICENSE: MIT license for all skill folders
2026-03-10 21:02:12 +01:00

174 lines
6.6 KiB
Python

#!/usr/bin/env python3
"""Memory Forensics Agent - Automates Volatility 3 analysis of memory dumps for incident response."""
import json
import logging
import argparse
import subprocess
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def run_volatility(memory_file, plugin, extra_args=None):
"""Execute a Volatility 3 plugin and return parsed output."""
cmd = ["vol", "-f", memory_file, plugin]
if extra_args:
cmd.extend(extra_args)
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
if result.returncode != 0:
logger.error("Volatility plugin %s failed: %s", plugin, result.stderr[:200])
return []
lines = result.stdout.strip().split("\n")
if len(lines) < 2:
return []
headers = [h.strip() for h in lines[0].split("\t")]
rows = []
for line in lines[1:]:
if line.strip() and not line.startswith("*"):
fields = [f.strip() for f in line.split("\t")]
if len(fields) == len(headers):
rows.append(dict(zip(headers, fields)))
logger.info("Plugin %s returned %d rows", plugin, len(rows))
return rows
def analyze_processes(memory_file):
"""List running processes and identify suspicious ones."""
processes = run_volatility(memory_file, "windows.pslist")
suspicious = []
suspicious_names = [
"mimikatz", "procdump", "psexec", "cobalt", "beacon", "meterpreter",
"nc.exe", "ncat", "powershell", "cmd.exe", "wscript", "cscript",
"certutil", "bitsadmin", "mshta", "regsvr32",
]
for proc in processes:
name = proc.get("ImageFileName", "").lower()
if any(s in name for s in suspicious_names):
proc["suspicious_reason"] = "Known offensive tool"
suspicious.append(proc)
logger.info("Processes: %d total, %d suspicious", len(processes), len(suspicious))
return processes, suspicious
def analyze_network_connections(memory_file):
"""Extract network connections and identify C2 communication."""
connections = run_volatility(memory_file, "windows.netscan")
established = [c for c in connections if c.get("State") == "ESTABLISHED"]
logger.info("Network connections: %d total, %d established", len(connections), len(established))
return connections, established
def detect_process_injection(memory_file):
"""Detect process injection using malfind plugin."""
malfind_results = run_volatility(memory_file, "windows.malfind")
injected = []
for entry in malfind_results:
injected.append({
"pid": entry.get("PID", ""),
"process": entry.get("Process", ""),
"start_vpn": entry.get("Start VPN", ""),
"protection": entry.get("Protection", ""),
"tag": entry.get("Tag", ""),
})
logger.info("Malfind: %d potential injections detected", len(injected))
return injected
def analyze_dlls(memory_file, pid=None):
"""List loaded DLLs for a process or all processes."""
args = ["--pid", str(pid)] if pid else None
dlls = run_volatility(memory_file, "windows.dlllist", args)
return dlls
def extract_command_history(memory_file):
"""Extract command line history from process memory."""
cmdline = run_volatility(memory_file, "windows.cmdline")
suspicious_cmds = []
indicators = [
"powershell -enc", "invoke-expression", "downloadstring", "net user",
"mimikatz", "sekurlsa", "lsadump", "reg save", "vssadmin",
"certutil -urlcache", "bitsadmin /transfer",
]
for entry in cmdline:
args = entry.get("Args", "").lower()
if any(ind in args for ind in indicators):
entry["suspicious_reason"] = "Suspicious command pattern"
suspicious_cmds.append(entry)
logger.info("Command lines: %d total, %d suspicious", len(cmdline), len(suspicious_cmds))
return cmdline, suspicious_cmds
def extract_registry_hives(memory_file):
"""List registry hives in memory."""
hives = run_volatility(memory_file, "windows.registry.hivelist")
logger.info("Registry hives: %d found", len(hives))
return hives
def check_kernel_modules(memory_file):
"""List kernel modules and detect potential rootkits."""
modules = run_volatility(memory_file, "windows.modules")
drivers = run_volatility(memory_file, "windows.driverscan")
hidden = []
module_names = {m.get("Name", "").lower() for m in modules}
for driver in drivers:
if driver.get("Name", "").lower() not in module_names:
hidden.append(driver)
logger.warning("Hidden driver detected: %s", driver.get("Name"))
return modules, hidden
def generate_forensics_report(memory_file, processes, suspicious_procs, connections,
injections, suspicious_cmds, hidden_drivers):
"""Generate memory forensics analysis report."""
report = {
"memory_image": memory_file,
"analysis_timestamp": datetime.utcnow().isoformat(),
"process_summary": {
"total": len(processes),
"suspicious": len(suspicious_procs),
"details": suspicious_procs[:20],
},
"network_connections": {
"established": len(connections),
"details": connections[:20],
},
"process_injection": {
"count": len(injections),
"details": injections[:20],
},
"suspicious_commands": suspicious_cmds[:20],
"hidden_drivers": hidden_drivers,
}
total_findings = len(suspicious_procs) + len(injections) + len(suspicious_cmds) + len(hidden_drivers)
print(f"MEMORY FORENSICS REPORT - {total_findings} findings")
return report
def main():
parser = argparse.ArgumentParser(description="Memory Forensics Agent (Volatility 3)")
parser.add_argument("--memory-file", required=True, help="Path to memory dump file")
parser.add_argument("--output", default="memory_forensics_report.json")
args = parser.parse_args()
processes, suspicious = analyze_processes(args.memory_file)
connections, established = analyze_network_connections(args.memory_file)
injections = detect_process_injection(args.memory_file)
cmdlines, suspicious_cmds = extract_command_history(args.memory_file)
modules, hidden = check_kernel_modules(args.memory_file)
report = generate_forensics_report(
args.memory_file, processes, suspicious, established,
injections, suspicious_cmds, hidden,
)
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", args.output)
if __name__ == "__main__":
main()