Files
Anthropic-Cybersecurity-Skills/skills/detecting-dll-sideloading-attacks/scripts/agent.py
T
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- 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
2026-03-19 13:26:49 +01:00

157 lines
5.7 KiB
Python

#!/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
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()