#!/usr/bin/env python3 """Fileless attack detection agent for endpoint logs. Detects in-memory attacks by analyzing PowerShell script block logs (Event 4104), WMI persistence events, and reflective DLL injection indicators from Sysmon. """ import argparse import json import re from datetime import datetime try: import Evtx.Evtx as evtx except ImportError: evtx = None SUSPICIOUS_PS_PATTERNS = { r"Invoke-Expression|IEX\s*\(": ("T1059.001", "HIGH", "Dynamic code execution"), r"Invoke-Mimikatz|Invoke-Kerberoast": ("T1003", "CRITICAL", "Credential tool"), r"System\.Reflection\.Assembly.*Load": ("T1620", "HIGH", "Reflective assembly load"), r"Net\.WebClient.*Download(String|Data|File)": ("T1105", "HIGH", "Remote download"), r"FromBase64String|Convert.*Base64": ("T1140", "MEDIUM", "Base64 decode"), r"VirtualAlloc|VirtualProtect|CreateThread": ("T1055", "CRITICAL", "Memory injection APIs"), r"New-Object.*IO\.MemoryStream": ("T1620", "HIGH", "In-memory stream"), r"-enc\s|-encodedcommand\s": ("T1027", "HIGH", "Encoded PowerShell"), r"Invoke-Shellcode|Invoke-ReflectivePEInjection": ("T1055", "CRITICAL", "Injection framework"), r"Win32_Process.*Create|WMI.*Process": ("T1047", "HIGH", "WMI process creation"), r"Register-WMI|__EventFilter|__EventConsumer": ("T1546.003", "CRITICAL", "WMI persistence"), r"HKCU:\\.*\\Run|HKLM:\\.*\\Run": ("T1547.001", "HIGH", "Registry run key"), r"Add-MpPreference.*ExclusionPath": ("T1562.001", "HIGH", "Defender exclusion"), } WMI_PERSISTENCE_EVENTS = { 19: "WMI EventFilter created", 20: "WMI EventConsumer created", 21: "WMI EventConsumerToFilter binding", } def parse_powershell_scriptblock(filepath): if evtx is None: return {"error": "python-evtx not installed: pip install python-evtx"} findings = [] with evtx.Evtx(filepath) as log: for record in log.records(): xml = record.xml() if "4104" not in xml: continue script_block = re.search(r'([^<]+)', xml) if not script_block: continue script = script_block.group(1) time_match = re.search(r'SystemTime="([^"]+)"', xml) for pattern, (mitre, severity, desc) in SUSPICIOUS_PS_PATTERNS.items(): if re.search(pattern, script, re.IGNORECASE): findings.append({ "event_id": 4104, "timestamp": time_match.group(1) if time_match else "", "pattern": desc, "mitre": mitre, "severity": severity, "script_excerpt": script[:300], }) return findings def parse_sysmon_wmi_persistence(filepath): if evtx is None: return {"error": "python-evtx not installed"} findings = [] with evtx.Evtx(filepath) as log: for record in log.records(): xml = record.xml() event_id_match = re.search(r']*>(\d+)', xml) if not event_id_match: continue event_id = int(event_id_match.group(1)) if event_id not in WMI_PERSISTENCE_EVENTS: continue time_match = re.search(r'SystemTime="([^"]+)"', xml) name = re.search(r'([^<]+)', xml) operation = re.search(r'([^<]+)', xml) consumer = re.search(r'([^<]+)', xml) user = re.search(r'([^<]+)', xml) findings.append({ "event_id": event_id, "type": WMI_PERSISTENCE_EVENTS[event_id], "timestamp": time_match.group(1) if time_match else "", "name": name.group(1) if name else "", "operation": operation.group(1) if operation else "", "destination": consumer.group(1) if consumer else "", "user": user.group(1) if user else "", "severity": "CRITICAL", "mitre": "T1546.003", }) return findings def parse_sysmon_injection(filepath): if evtx is None: return {"error": "python-evtx not installed"} findings = [] with evtx.Evtx(filepath) as log: for record in log.records(): xml = record.xml() if "8" not in xml: continue source = re.search(r'([^<]+)', xml) target = re.search(r'([^<]+)', xml) time_match = re.search(r'SystemTime="([^"]+)"', xml) findings.append({ "event_id": 8, "timestamp": time_match.group(1) if time_match else "", "source_image": source.group(1) if source else "", "target_image": target.group(1) if target else "", "severity": "HIGH", "mitre": "T1055", "description": "CreateRemoteThread - possible reflective injection", }) return findings def main(): parser = argparse.ArgumentParser(description="Fileless Attack Detector") parser.add_argument("--ps-log", help="PowerShell EVTX file (Event 4104)") parser.add_argument("--sysmon-log", help="Sysmon EVTX file") parser.add_argument("--check-wmi", action="store_true", help="Check WMI persistence") parser.add_argument("--check-injection", action="store_true", help="Check injection") args = parser.parse_args() results = {"timestamp": datetime.utcnow().isoformat() + "Z", "findings": []} if args.ps_log: ps = parse_powershell_scriptblock(args.ps_log) if isinstance(ps, dict) and "error" in ps: results["error"] = ps["error"] else: results["findings"].extend(ps) if args.sysmon_log and args.check_wmi: wmi = parse_sysmon_wmi_persistence(args.sysmon_log) if not isinstance(wmi, dict): results["findings"].extend(wmi) if args.sysmon_log and args.check_injection: inj = parse_sysmon_injection(args.sysmon_log) if not isinstance(inj, dict): results["findings"].extend(inj) results["total_findings"] = len(results["findings"]) print(json.dumps(results, indent=2)) if __name__ == "__main__": main()