mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 13:44: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
160 lines
6.3 KiB
Python
160 lines
6.3 KiB
Python
#!/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 "<EventID>4104</EventID>" not in xml:
|
|
continue
|
|
script_block = re.search(r'<Data Name="ScriptBlockText">([^<]+)', 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'<EventID[^>]*>(\d+)</EventID>', 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'<Data Name="Name">([^<]+)', xml)
|
|
operation = re.search(r'<Data Name="Operation">([^<]+)', xml)
|
|
consumer = re.search(r'<Data Name="Destination">([^<]+)', xml)
|
|
user = re.search(r'<Data Name="User">([^<]+)', 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 "<EventID>8</EventID>" not in xml:
|
|
continue
|
|
source = re.search(r'<Data Name="SourceImage">([^<]+)', xml)
|
|
target = re.search(r'<Data Name="TargetImage">([^<]+)', 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()
|