#!/usr/bin/env python3 """Agent for performing lateral movement detection and simulation with WMIExec — authorized testing only.""" import json import argparse import subprocess import re def detect_wmiexec_artifacts_evtx(evtx_file): """Detect WMIExec lateral movement artifacts in Windows Event Logs.""" try: import Evtx.Evtx as evtx import xml.etree.ElementTree as ET except ImportError: return {"error": "python-evtx not installed — pip install python-evtx"} ns = {"e": "http://schemas.microsoft.com/win/2004/08/events/event"} indicators = { "wmi_process_creation": [], "network_logon": [], "service_install": [], } with evtx.Evtx(evtx_file) as log: for record in log.records(): try: xml = record.xml() root = ET.fromstring(xml) eid_elem = root.find(".//e:EventID", ns) if eid_elem is None: continue eid = eid_elem.text data = {d.get("Name"): d.text for d in root.findall(".//e:Data", ns)} if eid == "1": parent = data.get("ParentImage", "").lower() cmdline = data.get("CommandLine", "") if "wmiprvse.exe" in parent: indicators["wmi_process_creation"].append({ "image": data.get("Image"), "cmdline": cmdline[:200], "user": data.get("User"), "parent": data.get("ParentImage"), }) elif eid == "4624": logon_type = data.get("LogonType", "") if logon_type == "3": indicators["network_logon"].append({ "user": data.get("TargetUserName"), "source_ip": data.get("IpAddress"), "workstation": data.get("WorkstationName"), }) elif eid == "7045": svc_name = data.get("ServiceName", "") if re.search(r"(BTOBTO|wmiprvse|wmi_|cmd\.exe)", svc_name, re.I): indicators["service_install"].append({ "service": svc_name, "path": data.get("ImagePath", "")[:200], }) except Exception: continue total = sum(len(v) for v in indicators.values()) return { "evtx_file": evtx_file, "total_indicators": total, "wmi_process_creations": len(indicators["wmi_process_creation"]), "network_logons": len(indicators["network_logon"]), "service_installs": len(indicators["service_install"]), "indicators": {k: v[:15] for k, v in indicators.items()}, "finding": "WMIEXEC_DETECTED" if total > 0 else "NO_INDICATORS", } def run_wmiexec_impacket(target, domain, username, command="whoami"): """Execute command via Impacket wmiexec (authorized pentest use).""" cmd = ["python3", "-m", "impacket.examples.wmiexec", f"{domain}/{username}@{target}", command] try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) return { "target": target, "domain": domain, "user": username, "command": command, "output": result.stdout[:500], "success": result.returncode == 0, "stderr": result.stderr[:200] if result.stderr else "", } except FileNotFoundError: return {"error": "Impacket not installed — pip install impacket"} except Exception as e: return {"error": str(e)} def detect_wmi_network_traffic(pcap_file): """Analyze PCAP for WMI lateral movement network indicators.""" cmd = ["tshark", "-r", pcap_file, "-Y", "dcerpc.cn_bind_uuid == 4d9f4ab8-7d1c-11cf-861e-0020af6e7c57 || tcp.port == 135 || dcom", "-T", "fields", "-e", "ip.src", "-e", "ip.dst", "-e", "tcp.dstport", "-e", "dcerpc.cn_bind_uuid", "-e", "frame.time"] try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) connections = [] for line in result.stdout.strip().splitlines(): parts = line.split("\t") if len(parts) >= 3: connections.append({"src": parts[0], "dst": parts[1], "port": parts[2], "uuid": parts[3] if len(parts) > 3 else "", "time": parts[4] if len(parts) > 4 else ""}) dcom_uuid = "4d9f4ab8-7d1c-11cf-861e-0020af6e7c57" wmi_traffic = [c for c in connections if c.get("uuid") == dcom_uuid or c.get("port") == "135"] return { "pcap_file": pcap_file, "total_connections": len(connections), "wmi_related": len(wmi_traffic), "connections": wmi_traffic[:20], } except FileNotFoundError: return {"error": "tshark not found — install Wireshark"} except Exception as e: return {"error": str(e)} def check_wmi_persistence(): """Check for WMI-based persistence mechanisms on local system.""" checks = { "event_subscriptions": ["wmic", "/namespace:\\\\root\\subscription", "path", "__EventFilter", "get", "/format:list"], "consumers": ["wmic", "/namespace:\\\\root\\subscription", "path", "CommandLineEventConsumer", "get", "/format:list"], "bindings": ["wmic", "/namespace:\\\\root\\subscription", "path", "__FilterToConsumerBinding", "get", "/format:list"], } results = {} for name, cmd in checks.items(): try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=15) entries = [line.strip() for line in result.stdout.splitlines() if "=" in line] results[name] = {"count": len(entries), "entries": entries[:10]} except Exception as e: results[name] = {"error": str(e)} total = sum(r.get("count", 0) for r in results.values() if isinstance(r.get("count"), int)) return {"wmi_persistence": results, "total_subscriptions": total, "finding": "WMI_PERSISTENCE_FOUND" if total > 0 else "NO_WMI_PERSISTENCE"} def main(): parser = argparse.ArgumentParser(description="WMIExec Lateral Movement Agent (Authorized Testing Only)") sub = parser.add_subparsers(dest="command") d = sub.add_parser("detect", help="Detect WMIExec in EVTX logs") d.add_argument("--evtx", required=True) e = sub.add_parser("exec", help="Execute via wmiexec (pentest)") e.add_argument("--target", required=True) e.add_argument("--domain", required=True) e.add_argument("--user", required=True) e.add_argument("--cmd", default="whoami") n = sub.add_parser("network", help="Analyze PCAP for WMI traffic") n.add_argument("--pcap", required=True) sub.add_parser("persistence", help="Check WMI persistence") args = parser.parse_args() if args.command == "detect": result = detect_wmiexec_artifacts_evtx(args.evtx) elif args.command == "exec": result = run_wmiexec_impacket(args.target, args.domain, args.user, args.cmd) elif args.command == "network": result = detect_wmi_network_traffic(args.pcap) elif args.command == "persistence": result = check_wmi_persistence() else: parser.print_help() return print(json.dumps(result, indent=2, default=str)) if __name__ == "__main__": main()