Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
T1046 on the official MITRE ATT&CK siteT1057 on the official MITRE ATT&CK siteT1082 on the official MITRE ATT&CK siteT1083 on the official MITRE ATT&CK siteT1176 on the official MITRE ATT&CK siteT1542.003 on the official MITRE ATT&CK siteT1546 on the official MITRE ATT&CK siteT1546.010 on the official MITRE ATT&CK siteT1546.012 on the official MITRE ATT&CK siteT1546.015 on the official MITRE ATT&CK siteT1547 on the official MITRE ATT&CK siteT1547.001 on the official MITRE ATT&CK siteT1547.004 on the official MITRE ATT&CK site
NIST CSF 2.0
MITRE D3FEND
When to Use
- When proactively hunting for indicators of hunting for registry persistence mechanisms in the environment
- After threat intelligence indicates active campaigns using these techniques
- During incident response to scope compromise related to these techniques
- When EDR or SIEM alerts trigger on related indicators
- During periodic security assessments and purple team exercises
Prerequisites
- EDR platform with process and network telemetry (CrowdStrike, MDE, SentinelOne)
- SIEM with relevant log data ingested (Splunk, Elastic, Sentinel)
- Sysmon deployed with comprehensive configuration
- Windows Security Event Log forwarding enabled
- Threat intelligence feeds for IOC correlation
Workflow
- Formulate Hypothesis: Define a testable hypothesis based on threat intelligence or ATT&CK gap analysis.
- Identify Data Sources: Determine which logs and telemetry are needed to validate or refute the hypothesis.
- Execute Queries: Run detection queries against SIEM and EDR platforms to collect relevant events.
- Analyze Results: Examine query results for anomalies, correlating across multiple data sources.
- Validate Findings: Distinguish true positives from false positives through contextual analysis.
- Correlate Activity: Link findings to broader attack chains and threat actor TTPs.
- Document and Report: Record findings, update detection rules, and recommend response actions.
Key Concepts
| Concept | Description |
|---|---|
| T1547.001 | Registry Run Keys |
| T1547.004 | Winlogon Helper DLL |
| T1546.012 | IFEO Injection |
| T1546.015 | COM Hijacking |
Tools & Systems
| Tool | Purpose |
|---|---|
| CrowdStrike Falcon | EDR telemetry and threat detection |
| Microsoft Defender for Endpoint | Advanced hunting with KQL |
| Splunk Enterprise | SIEM log analysis with SPL queries |
| Elastic Security | Detection rules and investigation timeline |
| Sysmon | Detailed Windows event monitoring |
| Velociraptor | Endpoint artifact collection and hunting |
| Sigma Rules | Cross-platform detection rule format |
Common Scenarios
- Scenario 1: Malware adding HKCU Run key for user-level persistence
- Scenario 2: Adversary modifying Winlogon Shell for system-level persistence
- Scenario 3: IFEO debugger injection for accessibility feature backdoor
- Scenario 4: COM object InprocServer32 hijack for DLL loading
Output Format
Hunt ID: TH-HUNTIN-[DATE]-[SEQ]
Technique: T1547.001
Host: [Hostname]
User: [Account context]
Evidence: [Log entries, process trees, network data]
Risk Level: [Critical/High/Medium/Low]
Confidence: [High/Medium/Low]
Recommended Action: [Containment, investigation, monitoring]Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md1.8 KB
API Reference — Hunting for Registry Persistence Mechanisms
Libraries Used
- subprocess: Execute
reg query /sto enumerate registry persistence keys - re: Pattern matching for suspicious values in registry entries
- json: Baseline file I/O and structured output
CLI Interface
python agent.py scan [--categories run_keys winlogon ifeo] [--save-baseline out.json]
python agent.py compare --baseline baseline.jsonCore Functions
scan_persistence_keys(categories=None)
Enumerates registry persistence keys across 8 categories and flags suspicious entries.
Parameters:
| Name | Type | Description |
|---|---|---|
categories |
list | Optional subset of categories to scan (default: all 8) |
Returns: dict with categories map, all_suspicious list, and total_suspicious count.
compare_baseline(baseline_file, current_scan=None)
Compares current registry state against a saved baseline to detect new persistence entries.
Parameters:
| Name | Type | Description |
|---|---|---|
baseline_file |
str | Path to baseline JSON file from previous scan |
Returns: dict with baseline_entries count, new_entries count, and findings list.
Registry Categories Scanned
| Category | Keys | MITRE Technique |
|---|---|---|
run_keys |
Run, RunOnce, RunOnceEx | T1547.001 |
winlogon |
Winlogon Shell, Userinit | T1547.004 |
ifeo |
Image File Execution Options | T1546.012 |
appinit |
AppInit_DLLs | T1546.010 |
shell_extensions |
ShellExecuteHooks | T1546.015 |
browser_helpers |
Browser Helper Objects | T1176 |
com_hijack |
CLSID overrides in HKCU | T1546.015 |
boot_execute |
BootExecute, Session Manager | T1542.003 |
Dependencies
No external packages required — uses Python standard library and reg.exe.
standards.md1.6 KB
Standards and References - Hunting For Registry Persistence Mechanisms
MITRE ATT&CK Mappings
| Technique | Name | Description |
|---|---|---|
| T1547.001 | Registry Run Keys | See attack.mitre.org/techniques/T1547/001 |
| T1547.004 | Winlogon Helper DLL | See attack.mitre.org/techniques/T1547/004 |
| T1546.012 | IFEO Injection | See attack.mitre.org/techniques/T1546/012 |
| T1546.015 | COM Hijacking | See attack.mitre.org/techniques/T1546/015 |
Detection Data Sources
| Source | Event ID | Purpose |
|---|---|---|
| Sysmon | 1 | Process creation with command line |
| Sysmon | 3 | Network connection initiated |
| Sysmon | 7 | Image loaded (DLL) |
| Sysmon | 10 | Process access (LSASS) |
| Sysmon | 11 | File creation |
| Sysmon | 12/13 | Registry create/set |
| Sysmon | 22 | DNS query |
| Sysmon | 25 | Process tampering |
| Windows Security | 4624 | Successful logon |
| Windows Security | 4625 | Failed logon |
| Windows Security | 4648 | Explicit credential logon |
| Windows Security | 4672 | Special privileges assigned |
| Windows Security | 4688 | Process creation |
| Windows Security | 4697 | Service installed |
| Windows Security | 4698 | Scheduled task created |
| Windows Security | 4769 | Kerberos TGS requested |
| Windows Security | 5140 | Network share accessed |
References
- MITRE ATT&CK Framework: https://attack.mitre.org/
- Sigma Detection Rules: https://github.com/SigmaHQ/sigma
- LOLBAS Project: https://lolbas-project.github.io/
- Atomic Red Team Tests: https://github.com/redcanaryco/atomic-red-team
- Red Canary Threat Detection Report
- SANS Threat Hunting Summit Resources
workflows.md2.9 KB
Detailed Hunting Workflow - Hunting For Registry Persistence Mechanisms
Phase 1: Data Collection and Querying
Splunk SPL Query
index=sysmon (EventCode=12 OR EventCode=13)
| where match(TargetObject, "(?i)\\\\CurrentVersion\\\\(Run|RunOnce|Policies\\\\Explorer\\\\Run)")
| table _time Computer User EventType TargetObject Details ImageKQL Query (Microsoft Defender for Endpoint)
DeviceRegistryEvents
| where RegistryKey has_any ("CurrentVersion\\Run","Winlogon\\Shell","Image File Execution Options")
| where ActionType in ("RegistryValueSet","RegistryKeyCreated")
| project Timestamp, DeviceName, RegistryKey, RegistryValueName, RegistryValueDataPhase 2: Baseline and Anomaly Detection
Step 2.1 - Establish Normal Behavior Baseline
- Collect 30 days of historical data for the targeted technique
- Document expected patterns, frequencies, and legitimate use cases
- Identify known false positive sources and document exceptions
- Build statistical baseline (mean, standard deviation) for key metrics
Step 2.2 - Identify Anomalies
- Compare current activity against the 30-day baseline
- Flag events exceeding 3 standard deviations from normal
- Prioritize anomalies by risk score and potential business impact
- Cross-reference with threat intelligence for known IOCs
Phase 3: Investigation and Correlation
Step 3.1 - Deep Dive Analysis
- For each anomaly, collect full process tree context
- Correlate with network activity, file operations, and authentication events
- Check binary signatures, file hashes, and certificate validity
- Review user account context and access patterns
Step 3.2 - Attack Chain Reconstruction
- Map findings to MITRE ATT&CK kill chain stages
- Identify initial access vector if applicable
- Trace lateral movement and privilege escalation paths
- Determine data access and potential exfiltration
Phase 4: Validation and Response
Step 4.1 - True/False Positive Determination
- Verify findings with system owners and IT operations
- Check change management records for authorized activities
- Validate user context (authorized actions vs. compromised account)
- Document determination rationale for each finding
Step 4.2 - Response Actions
- For confirmed threats: initiate incident response procedures
- For detection gaps: create or update detection rules
- For false positives: tune existing rules and update exclusions
- Update threat hunting playbook with lessons learned
Phase 5: Documentation and Reporting
Step 5.1 - Hunt Report
- Summarize hypothesis, methodology, and findings
- Include all queries executed and their results
- Document IOCs discovered and detection rules created
- Provide recommendations for security improvements
Step 5.2 - Knowledge Base Update
- Add findings to threat intelligence platform
- Update MITRE ATT&CK coverage heatmap
- Share detection rules via Sigma format
- Schedule follow-up hunts for related techniques
Scripts 2
agent.py5.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for hunting registry-based persistence mechanisms on Windows."""
import json
import argparse
import subprocess
import re
from datetime import datetime
PERSISTENCE_KEYS = {
"run_keys": [
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
r"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
r"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx",
],
"winlogon": [
r"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon",
],
"ifeo": [
r"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options",
],
"appinit": [
r"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows",
],
"shell_extensions": [
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks",
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad",
],
"browser_helpers": [
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects",
],
"com_hijack": [
r"HKCU\SOFTWARE\Classes\CLSID",
],
"boot_execute": [
r"HKLM\SYSTEM\CurrentControlSet\Control\Session Manager",
],
}
SUSPICIOUS_PATTERNS = [
r"\\temp\\", r"\\tmp\\", r"\\appdata\\local\\temp",
r"powershell.*-enc", r"powershell.*-nop",
r"cmd\.exe\s+/c\s+", r"mshta\.exe", r"rundll32\.exe.*javascript",
r"regsvr32\.exe.*/s\s+/n\s+/u\s+/i:",
r"\\users\\public\\", r"\\programdata\\[^m]",
r"certutil.*-decode", r"bitsadmin.*transfer",
r"base64", r"downloadstring", r"iex\s*\(",
]
def scan_persistence_keys(categories=None):
"""Scan specified registry persistence key categories."""
if categories is None:
categories = list(PERSISTENCE_KEYS.keys())
results = {"timestamp": datetime.utcnow().isoformat(), "categories": {}, "all_suspicious": []}
for category in categories:
keys = PERSISTENCE_KEYS.get(category, [])
category_findings = []
for key in keys:
try:
proc = subprocess.run(
["reg", "query", key, "/s"], capture_output=True, text=True, timeout=10
)
if proc.returncode == 0:
entries = _parse_reg(proc.stdout, key)
for entry in entries:
entry["suspicious"] = _check_suspicious(entry.get("value", ""))
entry["category"] = category
if entry["suspicious"]:
results["all_suspicious"].append(entry)
category_findings.extend(entries)
except (subprocess.TimeoutExpired, FileNotFoundError):
continue
results["categories"][category] = {
"total": len(category_findings),
"suspicious": sum(1 for f in category_findings if f.get("suspicious")),
"entries": category_findings,
}
results["total_suspicious"] = len(results["all_suspicious"])
return results
def _parse_reg(output, default_key):
entries = []
current_key = default_key
for line in output.strip().split("\n"):
line = line.strip()
if not line:
continue
if line.startswith("HK"):
current_key = line
continue
parts = re.split(r"\s{2,}", line, maxsplit=2)
if len(parts) >= 3:
entries.append({"key": current_key, "name": parts[0], "type": parts[1], "value": parts[2]})
return entries
def _check_suspicious(value):
return any(re.search(p, value, re.I) for p in SUSPICIOUS_PATTERNS)
def compare_baseline(baseline_file, current_scan=None):
"""Compare current registry state against a known-good baseline."""
with open(baseline_file, "r") as f:
baseline = json.load(f)
if current_scan is None:
current_scan = scan_persistence_keys()
baseline_set = set()
for cat_data in baseline.get("categories", {}).values():
for entry in cat_data.get("entries", []):
baseline_set.add((entry.get("key", ""), entry.get("name", ""), entry.get("value", "")))
new_entries = []
for cat_name, cat_data in current_scan["categories"].items():
for entry in cat_data.get("entries", []):
key_tuple = (entry.get("key", ""), entry.get("name", ""), entry.get("value", ""))
if key_tuple not in baseline_set:
entry["status"] = "NEW"
new_entries.append(entry)
return {
"baseline_entries": len(baseline_set),
"new_entries": len(new_entries),
"findings": new_entries,
}
def main():
parser = argparse.ArgumentParser(description="Hunt for registry persistence mechanisms")
sub = parser.add_subparsers(dest="command")
s = sub.add_parser("scan", help="Scan registry persistence keys")
s.add_argument("--categories", nargs="*", choices=list(PERSISTENCE_KEYS.keys()),
help="Categories to scan (default: all)")
s.add_argument("--save-baseline", help="Save scan as baseline JSON file")
c = sub.add_parser("compare", help="Compare against baseline")
c.add_argument("--baseline", required=True, help="Baseline JSON file")
args = parser.parse_args()
if args.command == "scan":
result = scan_persistence_keys(args.categories)
if args.save_baseline:
with open(args.save_baseline, "w") as f:
json.dump(result, f, indent=2)
elif args.command == "compare":
result = compare_baseline(args.baseline)
else:
parser.print_help()
return
print(json.dumps(result, indent=2, default=str))
if __name__ == "__main__":
main()
process.py3.6 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Registry Persistence Detection - Analyzes logs for T1547.001 indicators."""
import json, csv, argparse, datetime, re
from collections import defaultdict
from pathlib import Path
DETECTION_PATTERNS = [
r'CurrentVersion\\\\Run',
r'Winlogon\\\\Shell',
r'Image File Execution Options',
r'AppInit_DLLs',
r'InprocServer32',
r'Active Setup',
]
def parse_logs(path):
p = Path(path)
if p.suffix == ".json":
with open(p, encoding="utf-8") as f:
data = json.load(f)
return data if isinstance(data, list) else data.get("events", [])
elif p.suffix == ".csv":
with open(p, encoding="utf-8-sig") as f:
return [dict(r) for r in csv.DictReader(f)]
return []
def analyze_event(event):
cmd = event.get("CommandLine", event.get("command_line", event.get("ProcessCommandLine", "")))
content = event.get("Task_Content", event.get("Parameters", event.get("RawEventData", "")))
search_text = f"{cmd} {content}"
risk = 0
indicators = []
for pattern in DETECTION_PATTERNS:
if re.search(pattern, search_text, re.IGNORECASE):
risk += 25
indicators.append(f"Pattern match: {pattern}")
if not indicators:
return None
risk = min(risk, 100)
return {
"technique": "T1547.001",
"command_line": cmd[:500] if cmd else content[:500],
"hostname": event.get("Computer", event.get("DeviceName", event.get("hostname", "unknown"))),
"user": event.get("User", event.get("AccountName", event.get("UserId", "unknown"))),
"timestamp": event.get("_time", event.get("timestamp", event.get("UtcTime", event.get("Timestamp", "")))),
"risk_score": risk,
"risk_level": "CRITICAL" if risk >= 75 else "HIGH" if risk >= 50 else "MEDIUM" if risk >= 25 else "LOW",
"indicators": indicators,
}
def run_hunt(input_path, output_dir):
print(f"[*] Registry Persistence Hunt - {datetime.datetime.now().isoformat()}")
events = parse_logs(input_path)
findings = [f for f in (analyze_event(e) for e in events) if f]
Path(output_dir).mkdir(parents=True, exist_ok=True)
slug = "hunting_for_registry"
with open(Path(output_dir) / f"{slug}_findings.json", "w", encoding="utf-8") as f:
json.dump({"hunt_id": f"TH-{datetime.date.today()}", "total_events": len(events), "findings": findings}, f, indent=2)
with open(Path(output_dir) / "hunt_report.md", "w", encoding="utf-8") as f:
f.write(f"# Registry Persistence Hunt Report\n\n")
f.write(f"**Date**: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"**Findings**: {len(findings)}\n\n")
for finding in sorted(findings, key=lambda x: x["risk_score"], reverse=True)[:20]:
f.write(f"### [{finding['risk_level']}] {finding['technique']}\n")
f.write(f"- **Host**: {finding['hostname']}\n")
f.write(f"- **Indicators**: {', '.join(finding['indicators'])}\n\n")
print(f"[+] {len(findings)} findings written to {output_dir}")
def main():
p = argparse.ArgumentParser(description="Registry Persistence Detection")
sp = p.add_subparsers(dest="cmd")
h = sp.add_parser("hunt"); h.add_argument("--input", "-i", required=True); h.add_argument("--output", "-o", default="./hunting_for_reg_output")
sp.add_parser("queries")
args = p.parse_args()
if args.cmd == "hunt": run_hunt(args.input, args.output)
elif args.cmd == "queries":
print("=== Detection Queries ===")
print("See references/workflows.md for platform-specific queries")
else: p.print_help()
if __name__ == "__main__": main()
Assets 1
template.mdtext/markdown · 2.6 KBKeep exploring