mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-08 03:20:19 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
"""DLL sideloading detection agent using Sysmon Event ID 7 (Image Loaded) analysis.
|
||||
|
||||
Detects unsigned DLLs loaded by signed executables from non-standard paths,
|
||||
a common APT persistence and defense evasion technique (T1574.002).
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import Evtx.Evtx as evtx
|
||||
except ImportError:
|
||||
evtx = None
|
||||
|
||||
KNOWN_SIDELOAD_TARGETS = {
|
||||
"vmwaretray.exe": ["vmtools.dll"],
|
||||
"colorcpl.exe": ["colorui.dll"],
|
||||
"searchprotocolhost.exe": ["msfte.dll"],
|
||||
"consent.exe": ["comctl32.dll"],
|
||||
"dxcap.exe": ["d3d9.dll"],
|
||||
"eventvwr.exe": ["mmc.dll"],
|
||||
"msdeploy.exe": ["microsoft.web.deployment.dll"],
|
||||
"bginfo.exe": ["version.dll"],
|
||||
"winword.exe": ["wwlib.dll"],
|
||||
"teams.exe": ["version.dll"],
|
||||
}
|
||||
|
||||
STANDARD_DLL_DIRS = {
|
||||
r"c:\windows\system32", r"c:\windows\syswow64",
|
||||
r"c:\windows\winsxs", r"c:\program files",
|
||||
r"c:\program files (x86)",
|
||||
}
|
||||
|
||||
|
||||
def parse_sysmon_dll_loads(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>7</EventID>" not in xml:
|
||||
continue
|
||||
image = re.search(r'<Data Name="Image">([^<]+)', xml)
|
||||
loaded = re.search(r'<Data Name="ImageLoaded">([^<]+)', xml)
|
||||
signed = re.search(r'<Data Name="Signed">([^<]+)', xml)
|
||||
sig_status = re.search(r'<Data Name="SignatureStatus">([^<]+)', xml)
|
||||
sha256 = re.search(r'<Data Name="Hashes">([^<]+)', xml)
|
||||
time_created = re.search(r'SystemTime="([^"]+)"', xml)
|
||||
|
||||
if not image or not loaded:
|
||||
continue
|
||||
|
||||
image_path = image.group(1).lower()
|
||||
dll_path = loaded.group(1).lower()
|
||||
is_signed = signed.group(1) if signed else "unknown"
|
||||
image_name = image_path.rsplit("\\", 1)[-1]
|
||||
dll_name = dll_path.rsplit("\\", 1)[-1]
|
||||
dll_dir = dll_path.rsplit("\\", 1)[0] if "\\" in dll_path else ""
|
||||
|
||||
is_standard_dir = any(dll_dir.startswith(d) for d in STANDARD_DLL_DIRS)
|
||||
is_known_target = (image_name in KNOWN_SIDELOAD_TARGETS and
|
||||
dll_name in KNOWN_SIDELOAD_TARGETS[image_name])
|
||||
|
||||
if is_signed == "false" and not is_standard_dir:
|
||||
severity = "CRITICAL" if is_known_target else "HIGH"
|
||||
findings.append({
|
||||
"timestamp": time_created.group(1) if time_created else "",
|
||||
"host_process": image_path,
|
||||
"loaded_dll": dll_path,
|
||||
"signed": is_signed,
|
||||
"signature_status": sig_status.group(1) if sig_status else "",
|
||||
"hash": sha256.group(1) if sha256 else "",
|
||||
"known_sideload_target": is_known_target,
|
||||
"non_standard_path": True,
|
||||
"severity": severity,
|
||||
"mitre": "T1574.002",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def scan_directory_for_sideloading(directory):
|
||||
findings = []
|
||||
dir_path = Path(directory)
|
||||
if not dir_path.is_dir():
|
||||
return [{"error": f"Directory not found: {directory}"}]
|
||||
exe_files = list(dir_path.glob("*.exe"))
|
||||
dll_files = list(dir_path.glob("*.dll"))
|
||||
for exe in exe_files:
|
||||
exe_name = exe.name.lower()
|
||||
if exe_name in KNOWN_SIDELOAD_TARGETS:
|
||||
for dll in dll_files:
|
||||
if dll.name.lower() in KNOWN_SIDELOAD_TARGETS[exe_name]:
|
||||
findings.append({
|
||||
"exe_path": str(exe),
|
||||
"dll_path": str(dll),
|
||||
"dll_size_bytes": dll.stat().st_size,
|
||||
"known_sideload_pair": True,
|
||||
"severity": "CRITICAL",
|
||||
"mitre": "T1574.002",
|
||||
"description": f"Known sideloading pair: {exe.name} + {dll.name}",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def generate_sigma_rule():
|
||||
return {
|
||||
"title": "DLL Sideloading - Unsigned DLL in Non-Standard Path",
|
||||
"status": "experimental",
|
||||
"logsource": {"product": "windows", "category": "image_load"},
|
||||
"detection": {
|
||||
"selection": {"EventID": 7, "Signed": "false"},
|
||||
"filter_standard": {"ImageLoaded|startswith": [
|
||||
"C:\\Windows\\System32\\", "C:\\Windows\\SysWOW64\\",
|
||||
"C:\\Program Files\\", "C:\\Program Files (x86)\\"
|
||||
]},
|
||||
"condition": "selection and not filter_standard"
|
||||
},
|
||||
"level": "high",
|
||||
"tags": ["attack.defense_evasion", "attack.t1574.002"],
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="DLL Sideloading Detector")
|
||||
parser.add_argument("--sysmon-log", help="Sysmon EVTX file with Event ID 7")
|
||||
parser.add_argument("--scan-dir", help="Directory to scan for sideloading pairs")
|
||||
parser.add_argument("--generate-sigma", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
results = {"timestamp": datetime.utcnow().isoformat() + "Z", "findings": []}
|
||||
|
||||
if args.sysmon_log:
|
||||
evtx_findings = parse_sysmon_dll_loads(args.sysmon_log)
|
||||
if isinstance(evtx_findings, dict) and "error" in evtx_findings:
|
||||
results["error"] = evtx_findings["error"]
|
||||
else:
|
||||
results["findings"].extend(evtx_findings)
|
||||
|
||||
if args.scan_dir:
|
||||
dir_findings = scan_directory_for_sideloading(args.scan_dir)
|
||||
results["findings"].extend(dir_findings)
|
||||
|
||||
if args.generate_sigma:
|
||||
results["sigma_rule"] = generate_sigma_rule()
|
||||
|
||||
results["total_findings"] = len(results["findings"])
|
||||
print(json.dumps(results, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user