#!/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()