mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-14 15:04:56 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
216 lines
7.6 KiB
Python
216 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Sysmon scheduled task detection agent for hunting malicious persistence."""
|
|
|
|
import json
|
|
import argparse
|
|
import re
|
|
import base64
|
|
import xml.etree.ElementTree as ET
|
|
from datetime import datetime
|
|
|
|
|
|
SUSPICIOUS_PATHS = [
|
|
r"\\users\\public\\", r"\\programdata\\", r"\\windows\\temp\\",
|
|
r"\\appdata\\local\\temp\\", r"\\downloads\\", r"\\desktop\\",
|
|
r"c:\\temp\\", r"\\recycle",
|
|
]
|
|
|
|
SUSPICIOUS_COMMANDS = [
|
|
r"powershell.*-enc", r"powershell.*-e\s+", r"powershell.*downloadstring",
|
|
r"powershell.*iex", r"powershell.*invoke-expression",
|
|
r"cmd.*/c\s+", r"mshta\s+", r"certutil.*-urlcache",
|
|
r"bitsadmin.*/transfer", r"regsvr32.*/s.*/u",
|
|
r"rundll32.*javascript", r"wscript.*\.vbs",
|
|
]
|
|
|
|
|
|
def parse_evtx_xml(xml_path):
|
|
"""Parse exported Windows Event Log XML for Sysmon and Security events."""
|
|
events = []
|
|
try:
|
|
tree = ET.parse(xml_path)
|
|
root = tree.getroot()
|
|
ns = {"e": "http://schemas.microsoft.com/win/2004/08/events/event"}
|
|
for event_el in root.findall(".//e:Event", ns):
|
|
system = event_el.find("e:System", ns)
|
|
event_data = event_el.find("e:EventData", ns)
|
|
if system is None:
|
|
continue
|
|
event_id = int(system.findtext("e:EventID", "0", ns))
|
|
data = {}
|
|
if event_data is not None:
|
|
for d in event_data.findall("e:Data", ns):
|
|
name = d.get("Name", "")
|
|
data[name] = d.text or ""
|
|
events.append({
|
|
"event_id": event_id,
|
|
"timestamp": system.findtext("e:TimeCreated/@SystemTime", "", ns)
|
|
or system.find("e:TimeCreated", ns).get("SystemTime", "") if system.find("e:TimeCreated", ns) is not None else "",
|
|
"computer": system.findtext("e:Computer", "", ns),
|
|
"data": data,
|
|
})
|
|
except ET.ParseError as e:
|
|
return [{"error": f"XML parse error: {e}"}]
|
|
return events
|
|
|
|
|
|
def detect_schtasks_creation(events):
|
|
"""Detect suspicious schtasks.exe process creation (Sysmon Event 1)."""
|
|
findings = []
|
|
for evt in events:
|
|
if evt["event_id"] != 1:
|
|
continue
|
|
image = evt["data"].get("Image", "").lower()
|
|
cmdline = evt["data"].get("CommandLine", "")
|
|
parent = evt["data"].get("ParentImage", "")
|
|
|
|
if "schtasks" not in image and "at.exe" not in image:
|
|
continue
|
|
if "/create" not in cmdline.lower() and "/change" not in cmdline.lower():
|
|
continue
|
|
|
|
severity = "MEDIUM"
|
|
reasons = []
|
|
|
|
for pattern in SUSPICIOUS_PATHS:
|
|
if re.search(pattern, cmdline, re.IGNORECASE):
|
|
severity = "HIGH"
|
|
reasons.append(f"Task executes from suspicious path: {pattern}")
|
|
|
|
for pattern in SUSPICIOUS_COMMANDS:
|
|
if re.search(pattern, cmdline, re.IGNORECASE):
|
|
severity = "CRITICAL"
|
|
reasons.append(f"Suspicious command pattern: {pattern}")
|
|
|
|
if "/s " in cmdline.lower() or "/s\t" in cmdline:
|
|
severity = "CRITICAL"
|
|
reasons.append("Remote task creation detected (lateral movement)")
|
|
|
|
if "-enc" in cmdline.lower() or "-e " in cmdline.lower():
|
|
encoded = re.search(r'-[eE](?:nc)?\s+([A-Za-z0-9+/=]{20,})', cmdline)
|
|
if encoded:
|
|
try:
|
|
decoded = base64.b64decode(encoded.group(1)).decode("utf-16-le", errors="replace")
|
|
reasons.append(f"Decoded command: {decoded[:150]}")
|
|
except Exception:
|
|
pass
|
|
|
|
if not reasons:
|
|
reasons.append("Scheduled task creation detected")
|
|
|
|
findings.append({
|
|
"timestamp": evt["timestamp"],
|
|
"computer": evt["computer"],
|
|
"image": image,
|
|
"command_line": cmdline[:300],
|
|
"parent_process": parent,
|
|
"user": evt["data"].get("User", ""),
|
|
"severity": severity,
|
|
"reasons": reasons,
|
|
"mitre": "T1053.005",
|
|
})
|
|
return findings
|
|
|
|
|
|
def detect_task_file_creation(events):
|
|
"""Detect task XML file creation in System32\\Tasks (Sysmon Event 11)."""
|
|
findings = []
|
|
for evt in events:
|
|
if evt["event_id"] != 11:
|
|
continue
|
|
target = evt["data"].get("TargetFilename", "")
|
|
if "\\windows\\system32\\tasks\\" not in target.lower():
|
|
continue
|
|
process = evt["data"].get("Image", "")
|
|
findings.append({
|
|
"timestamp": evt["timestamp"],
|
|
"task_file": target,
|
|
"created_by": process,
|
|
"severity": "MEDIUM",
|
|
"detail": "New scheduled task XML file created",
|
|
})
|
|
return findings
|
|
|
|
|
|
def detect_event_4698(events):
|
|
"""Detect Security Event 4698 — scheduled task registered."""
|
|
findings = []
|
|
for evt in events:
|
|
if evt["event_id"] != 4698:
|
|
continue
|
|
task_name = evt["data"].get("TaskName", "")
|
|
task_content = evt["data"].get("TaskContent", "")
|
|
user = evt["data"].get("SubjectUserName", "")
|
|
severity = "MEDIUM"
|
|
reasons = []
|
|
|
|
for pattern in SUSPICIOUS_COMMANDS:
|
|
if re.search(pattern, task_content, re.IGNORECASE):
|
|
severity = "CRITICAL"
|
|
reasons.append(f"Task content contains: {pattern}")
|
|
|
|
findings.append({
|
|
"timestamp": evt["timestamp"],
|
|
"task_name": task_name,
|
|
"registered_by": user,
|
|
"severity": severity,
|
|
"reasons": reasons or ["New task registered"],
|
|
"task_content_preview": task_content[:200],
|
|
})
|
|
return findings
|
|
|
|
|
|
def run_audit(args):
|
|
"""Execute scheduled task detection audit."""
|
|
print(f"\n{'='*60}")
|
|
print(f" MALICIOUS SCHEDULED TASK DETECTION")
|
|
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
|
print(f"{'='*60}\n")
|
|
|
|
report = {}
|
|
|
|
if args.evtx_xml:
|
|
events = parse_evtx_xml(args.evtx_xml)
|
|
report["total_events"] = len(events)
|
|
print(f"Parsed {len(events)} events from {args.evtx_xml}\n")
|
|
|
|
schtask_findings = detect_schtasks_creation(events)
|
|
report["schtasks_findings"] = schtask_findings
|
|
print(f"--- SCHTASKS CREATION (Event 1) — {len(schtask_findings)} findings ---")
|
|
for f in schtask_findings[:15]:
|
|
print(f" [{f['severity']}] {f['computer']}: {f['command_line'][:80]}")
|
|
for r in f["reasons"]:
|
|
print(f" -> {r[:100]}")
|
|
|
|
file_findings = detect_task_file_creation(events)
|
|
report["task_file_findings"] = file_findings
|
|
print(f"\n--- TASK FILE CREATION (Event 11) — {len(file_findings)} findings ---")
|
|
for f in file_findings[:10]:
|
|
print(f" [{f['severity']}] {f['task_file']}")
|
|
|
|
reg_findings = detect_event_4698(events)
|
|
report["event_4698_findings"] = reg_findings
|
|
print(f"\n--- TASK REGISTRATION (Event 4698) — {len(reg_findings)} findings ---")
|
|
for f in reg_findings[:10]:
|
|
print(f" [{f['severity']}] {f['task_name']} by {f['registered_by']}")
|
|
|
|
return report
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Sysmon Scheduled Task Detection Agent")
|
|
parser.add_argument("--evtx-xml", required=True,
|
|
help="Exported event log XML file to analyze")
|
|
parser.add_argument("--output", help="Save report to JSON file")
|
|
args = parser.parse_args()
|
|
|
|
report = run_audit(args)
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"\n[+] Report saved to {args.output}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|