#!/usr/bin/env python3 """ Endpoint Evasion Technique Detector Analyzes Windows event logs (exported as EVTX/CSV) for common defense evasion techniques mapped to MITRE ATT&CK TA0005. """ import json import csv import re import sys import os from collections import defaultdict from datetime import datetime EVASION_PATTERNS = { "T1070.001-log_clearing": { "name": "Indicator Removal: Clear Windows Event Logs", "severity": "high", "patterns": [ r"wevtutil\s+(cl|clear-log)", r"Clear-EventLog", r"Remove-EventLog", ], "event_ids": ["1102", "104"], }, "T1055-process_injection": { "name": "Process Injection", "severity": "high", "sysmon_event_ids": ["8", "10", "25"], "patterns": [ r"VirtualAllocEx", r"WriteProcessMemory", r"CreateRemoteThread", r"NtMapViewOfSection", ], }, "T1562.001-disable_security": { "name": "Impair Defenses: Disable or Modify Tools", "severity": "critical", "patterns": [ r"Set-MpPreference\s+-Disable", r"sc\s+(stop|config)\s+(WinDefend|Sense|MBAMService)", r"net\s+stop\s+(windefend|sense|csagent)", r"DisableAntiSpyware", r"DisableRealtimeMonitoring", ], }, "T1036-masquerading": { "name": "Masquerading", "severity": "medium", "suspicious_paths": { "svchost.exe": r"C:\\Windows\\System32\\svchost\.exe", "csrss.exe": r"C:\\Windows\\System32\\csrss\.exe", "lsass.exe": r"C:\\Windows\\System32\\lsass\.exe", "smss.exe": r"C:\\Windows\\System32\\smss\.exe", "services.exe": r"C:\\Windows\\System32\\services\.exe", }, }, "T1218-lolbin_abuse": { "name": "System Binary Proxy Execution", "severity": "high", "patterns": [ r"mshta\.exe.*https?://", r"mshta\.exe.*javascript:", r"certutil\.exe.*-urlcache", r"certutil\.exe.*-decode", r"regsvr32\.exe.*/s.*/n.*/u.*/i:", r"rundll32\.exe.*javascript:", r"MSBuild\.exe(?!.*\.(sln|csproj|vbproj))", r"installutil\.exe.*/logfile=", ], }, "T1070.006-timestomping": { "name": "Indicator Removal: Timestomp", "severity": "medium", "sysmon_event_ids": ["2"], }, } def analyze_sysmon_csv(csv_path: str) -> list: """Analyze Sysmon events exported as CSV for evasion techniques.""" detections = [] with open(csv_path, "r", encoding="utf-8-sig") as f: reader = csv.DictReader(f) for row in reader: event_id = row.get("Event ID", row.get("EventID", "")) message = row.get("Message", row.get("Details", "")) command_line = row.get("CommandLine", "") image = row.get("Image", row.get("Process Name", "")) timestamp = row.get("Date and Time", row.get("TimeCreated", "")) full_text = f"{message} {command_line} {image}".lower() for technique_id, technique in EVASION_PATTERNS.items(): detected = False detection_detail = "" if "event_ids" in technique and event_id in technique["event_ids"]: detected = True detection_detail = f"Event ID {event_id} detected" if "sysmon_event_ids" in technique and event_id in technique["sysmon_event_ids"]: detected = True detection_detail = f"Sysmon Event ID {event_id}" for pattern in technique.get("patterns", []): if re.search(pattern, full_text, re.IGNORECASE): detected = True detection_detail = f"Pattern match: {pattern}" break if "suspicious_paths" in technique and image: image_lower = image.lower() for proc_name, expected_path in technique["suspicious_paths"].items(): if proc_name in image_lower: if not re.match(expected_path, image, re.IGNORECASE): detected = True detection_detail = f"Masquerading: {proc_name} from unexpected path {image}" if detected: detections.append({ "timestamp": timestamp, "technique_id": technique_id.split("-")[0], "technique_name": technique["name"], "severity": technique["severity"], "event_id": event_id, "process": image, "command_line": command_line[:300], "detail": detection_detail, "host": row.get("Computer", row.get("host", "")), }) return detections def generate_detection_report(detections: list, output_path: str) -> None: """Generate evasion detection report.""" by_technique = defaultdict(list) by_severity = defaultdict(int) by_host = defaultdict(int) for d in detections: by_technique[d["technique_id"]].append(d) by_severity[d["severity"]] += 1 by_host[d["host"]] += 1 report = { "report_generated": datetime.utcnow().isoformat() + "Z", "total_detections": len(detections), "summary": { "by_severity": dict(by_severity), "by_technique": {k: len(v) for k, v in by_technique.items()}, "by_host": dict(by_host), }, "detections": detections[:200], } with open(output_path, "w", encoding="utf-8") as f: json.dump(report, f, indent=2) if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python process.py ") print() print("Analyzes exported Sysmon/Windows event logs for defense evasion techniques.") sys.exit(1) csv_path = sys.argv[1] if not os.path.exists(csv_path): print(f"Error: File not found: {csv_path}") sys.exit(1) print("Analyzing endpoint logs for evasion techniques...") detections = analyze_sysmon_csv(csv_path) base = os.path.splitext(os.path.basename(csv_path))[0] out_dir = os.path.dirname(csv_path) or "." report_path = os.path.join(out_dir, f"{base}_evasion_report.json") generate_detection_report(detections, report_path) print(f"Detection report: {report_path}") print(f"\n--- Evasion Detection Summary ---") print(f"Total detections: {len(detections)}") severity_counts = defaultdict(int) technique_counts = defaultdict(int) for d in detections: severity_counts[d["severity"]] += 1 technique_counts[d["technique_id"]] += 1 for sev in ["critical", "high", "medium", "low"]: if severity_counts[sev]: print(f" {sev.upper()}: {severity_counts[sev]}") if technique_counts: print(f"\nBy technique:") for tid, count in sorted(technique_counts.items(), key=lambda x: -x[1]): print(f" {tid}: {count}")