mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-25 05:50:57 +03:00
- 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
185 lines
6.8 KiB
Python
185 lines
6.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Detect Living Off the Land Binaries (LOLBAS) abuse via process telemetry and Sigma rules."""
|
|
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
from collections import defaultdict
|
|
|
|
LOLBIN_SIGNATURES = {
|
|
"certutil.exe": {
|
|
"suspicious_args": ["-urlcache", "-split", "-decode", "-encode", "-f http", "-verifyctl"],
|
|
"mitre": "T1140",
|
|
"description": "Certificate utility abused for download/decode",
|
|
},
|
|
"mshta.exe": {
|
|
"suspicious_args": ["http://", "https://", "javascript:", "vbscript:", ".hta"],
|
|
"mitre": "T1218.005",
|
|
"description": "HTML Application host executing remote content",
|
|
},
|
|
"regsvr32.exe": {
|
|
"suspicious_args": ["/s /n /u /i:http", "/i:http", "scrobj.dll", ".sct"],
|
|
"mitre": "T1218.010",
|
|
"description": "COM scriptlet execution via regsvr32 (Squiblydoo)",
|
|
},
|
|
"rundll32.exe": {
|
|
"suspicious_args": ["javascript:", "http://", "shell32.dll,ShellExec_RunDLL", "comsvcs.dll,MiniDump"],
|
|
"mitre": "T1218.011",
|
|
"description": "Rundll32 proxy execution or credential dumping",
|
|
},
|
|
"msbuild.exe": {
|
|
"suspicious_args": [".xml", ".csproj", "/p:", "inline task"],
|
|
"mitre": "T1127.001",
|
|
"description": "MSBuild inline task code execution",
|
|
},
|
|
"bitsadmin.exe": {
|
|
"suspicious_args": ["/transfer", "/create", "/addfile", "/resume", "/complete"],
|
|
"mitre": "T1197",
|
|
"description": "BITS job used for file download or persistence",
|
|
},
|
|
"wmic.exe": {
|
|
"suspicious_args": ["process call create", "/node:", "os get", "format:"],
|
|
"mitre": "T1047",
|
|
"description": "WMI command-line for execution or reconnaissance",
|
|
},
|
|
"cmstp.exe": {
|
|
"suspicious_args": ["/ni", "/s", ".inf"],
|
|
"mitre": "T1218.003",
|
|
"description": "CMSTP UAC bypass with malicious INF",
|
|
},
|
|
}
|
|
|
|
SUSPICIOUS_PARENTS = {
|
|
"winword.exe", "excel.exe", "powerpnt.exe", "outlook.exe",
|
|
"wmiprvse.exe", "svchost.exe", "taskeng.exe", "cmd.exe",
|
|
}
|
|
|
|
|
|
def parse_process_events(log_path):
|
|
"""Parse Sysmon or Windows 4688 process creation events from JSON log."""
|
|
events = []
|
|
with open(log_path) as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
try:
|
|
event = json.loads(line)
|
|
events.append(event)
|
|
except json.JSONDecodeError:
|
|
continue
|
|
return events
|
|
|
|
|
|
def detect_lolbin_abuse(events):
|
|
"""Detect LOLBin abuse from process creation events."""
|
|
detections = []
|
|
for event in events:
|
|
image = event.get("Image", event.get("NewProcessName", "")).lower()
|
|
cmdline = event.get("CommandLine", event.get("ProcessCommandLine", "")).lower()
|
|
parent = event.get("ParentImage", event.get("ParentProcessName", "")).lower()
|
|
binary_name = image.rsplit("\\", 1)[-1] if "\\" in image else image.rsplit("/", 1)[-1]
|
|
|
|
if binary_name not in LOLBIN_SIGNATURES:
|
|
continue
|
|
|
|
sig = LOLBIN_SIGNATURES[binary_name]
|
|
matched_args = [arg for arg in sig["suspicious_args"] if arg.lower() in cmdline]
|
|
if not matched_args:
|
|
continue
|
|
|
|
parent_name = parent.rsplit("\\", 1)[-1] if "\\" in parent else parent.rsplit("/", 1)[-1]
|
|
parent_suspicious = parent_name in SUSPICIOUS_PARENTS
|
|
|
|
severity = "high" if parent_suspicious else "medium"
|
|
if len(matched_args) > 1:
|
|
severity = "critical"
|
|
|
|
detections.append({
|
|
"timestamp": event.get("UtcTime", event.get("TimeCreated", datetime.utcnow().isoformat())),
|
|
"binary": binary_name,
|
|
"command_line": event.get("CommandLine", event.get("ProcessCommandLine", "")),
|
|
"parent_process": parent,
|
|
"parent_suspicious": parent_suspicious,
|
|
"matched_signatures": matched_args,
|
|
"mitre_technique": sig["mitre"],
|
|
"description": sig["description"],
|
|
"severity": severity,
|
|
"user": event.get("User", event.get("SubjectUserName", "unknown")),
|
|
"pid": event.get("ProcessId", event.get("NewProcessId", "")),
|
|
})
|
|
return detections
|
|
|
|
|
|
def generate_sigma_rule(binary_name):
|
|
"""Generate a Sigma detection rule for a specific LOLBin."""
|
|
if binary_name not in LOLBIN_SIGNATURES:
|
|
return None
|
|
sig = LOLBIN_SIGNATURES[binary_name]
|
|
rule = {
|
|
"title": f"Suspicious {binary_name} Execution",
|
|
"id": f"lolbas-{binary_name.replace('.exe', '')}-detection",
|
|
"status": "experimental",
|
|
"description": sig["description"],
|
|
"references": ["https://lolbas-project.github.io/"],
|
|
"logsource": {"category": "process_creation", "product": "windows"},
|
|
"detection": {
|
|
"selection": {"Image|endswith": f"\\{binary_name}"},
|
|
"condition_args": {
|
|
"CommandLine|contains": sig["suspicious_args"]
|
|
},
|
|
"condition": "selection and condition_args",
|
|
},
|
|
"falsepositives": ["Legitimate administrative use"],
|
|
"level": "high",
|
|
"tags": [f"attack.{sig['mitre'].lower()}"],
|
|
}
|
|
return rule
|
|
|
|
|
|
def build_report(detections, log_path):
|
|
"""Build structured detection report."""
|
|
by_binary = defaultdict(list)
|
|
for d in detections:
|
|
by_binary[d["binary"]].append(d)
|
|
|
|
severity_counts = defaultdict(int)
|
|
for d in detections:
|
|
severity_counts[d["severity"]] += 1
|
|
|
|
return {
|
|
"report_time": datetime.utcnow().isoformat(),
|
|
"log_source": log_path,
|
|
"total_detections": len(detections),
|
|
"severity_summary": dict(severity_counts),
|
|
"detections_by_binary": {k: len(v) for k, v in by_binary.items()},
|
|
"mitre_techniques": list({d["mitre_technique"] for d in detections}),
|
|
"detections": detections,
|
|
}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="LOLBAS Abuse Detection Agent")
|
|
parser.add_argument("--log-file", required=True, help="JSON log file with process creation events")
|
|
parser.add_argument("--output", default="lolbas_detections.json", help="Output report path")
|
|
parser.add_argument("--generate-sigma", action="store_true", help="Generate Sigma rules for all LOLBins")
|
|
args = parser.parse_args()
|
|
|
|
events = parse_process_events(args.log_file)
|
|
detections = detect_lolbin_abuse(events)
|
|
report = build_report(detections, args.log_file)
|
|
|
|
if args.generate_sigma:
|
|
report["sigma_rules"] = {}
|
|
for binary in LOLBIN_SIGNATURES:
|
|
report["sigma_rules"][binary] = generate_sigma_rule(binary)
|
|
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"[+] Analyzed {len(events)} events, found {len(detections)} LOLBin abuse detections")
|
|
print(f"[+] Report saved to {args.output}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|